LEFT OUTER присоединяется к Rails 3

У меня есть следующий код:

@posts = Post.joins(:user).joins(:blog).select

который предназначен для поиска всех сообщений и их возврата, а также связанных пользователей и блогов. Тем не менее, пользователи являются необязательными, что означает, что INNER JOIN, который генерирует :joins, не возвращает много записей.

Как использовать это для генерации LEFT OUTER JOIN вместо этого?

Ответ 1

@posts = Post.joins("LEFT OUTER JOIN users ON users.id = posts.user_id").
              joins(:blog).select

Ответ 2

Вы можете сделать это с помощью includes как описано в руководстве Rails:

Post.includes(:comments).where(comments: {visible: true})

Результаты в:

SELECT "posts"."id" AS t0_r0, ...
       "comments"."updated_at" AS t1_r5
FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id"
WHERE (comments.visible = 1)

Ответ 3

Я большой поклонник squeel gem:

Post.joins{user.outer}.joins{blog}

Он поддерживает как объединения inner, так и outer, а также возможность указывать класс/тип для полиморфных отношений belongs_to.

Ответ 4

Используйте eager_load:

@posts = Post.eager_load(:user)

Ответ 5

По умолчанию при передаче ActiveRecord::Base#joins именованной ассоциации он выполняет INNER JOIN. Вам нужно будет передать строку, представляющую ваш LEFT OUTER JOIN.

Из документация:

:joins - либо фрагмент SQL для дополнительных объединений, как "LEFT JOIN comments ON comments.post_id = id" (редко требуется), называемые ассоциациями в той же форме, что и для опции :include, которая будет выполнять INNER JOIN в связанной таблице (таблицах) или массиве, содержащем смесь обеих строк и названных ассоциаций.

Если значение равно строка, то записи будут возвращены только для чтения, так как они будут имеют атрибуты, которые не соответствуют столбцам таблицы. Проходить :readonly => false для отмены.

Ответ 6

В activerecord есть метод left_outer_joins. Вы можете использовать его следующим образом:

@posts = Post.left_outer_joins(:user).joins(:blog).select

Ответ 7

Хорошие новости, Rails 5 теперь поддерживает LEFT OUTER JOIN. Теперь ваш запрос будет выглядеть следующим образом:

@posts = Post.left_outer_joins(:user, :blog)

Ответ 8

class User < ActiveRecord::Base
     has_many :friends, :foreign_key=>"u_from",:class_name=>"Friend"
end

class Friend < ActiveRecord::Base
     belongs_to :user
end


friends = user.friends.where(:u_req_status=>2).joins("LEFT OUTER JOIN users ON users.u_id = friends.u_to").select("friend_id,u_from,u_to,u_first_name,u_last_name,u_email,u_fbid,u_twtid,u_picture_url,u_quote")