У меня есть следующий код:
@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")