LEFT OUTER加入Rails 3


Answers:


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

3
如果您只想要没有用户的帖子怎么办?
mcr

24
@mcr@posts = Post.joins("LEFT OUTER JOIN users ON users.id = posts.user_id").joins(:blog).where("users.id IS NULL").select
Linus Oleander

1
选择不需要参数吗?这不是select('posts.*')吗?
凯文·西尔维斯特

在Rails 3中,这是真正控制联接并确切知道正在发生什么的唯一方法。
约书亚·品特

75

您可以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)

14
根据我的测试includes,不执行联接,而是执行单独的查询以获取关联。因此,它避免了N + 1,但避免了与在一个查询中获取记录的JOIN不同的方式。
克里斯(Kris)

7
@Kris在某种程度上你是对的。您需要注意这一点,因为includes函数会同时使用这两个函数,具体取决于您在其中使用的上下文。Rails
WuTangTan

4
这只会部分回答问题,因为如果您不需要includes,则会生成2个查询,而不是一个查询。JOINWHERE
罗德里格

14
除非另外添加,否则这会在Rails 4中生成警告references(:comments)。另外,由于,这将导致所有返回的注释都急切地加载到内存中includes,这可能不是您想要的。
德里克

2
为了使这个更“Railsy”: Post.includes(:comments).where(comments: {visible: true})。这样,您也无需使用references
迈克尔,

11

我是squeel gem的忠实粉丝:

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

它同时支持innerouter联接,还可以为多态的belongs_to关系指定类/类型。



8

默认情况下,当您传递ActiveRecord::Base#joins命名关联时,它将执行INNER JOIN。您必须传递一个表示您的LEFT OUTER JOIN的字符串。

文档中

:joins-用于附加连接的SQL片段,例如“ LEFT JOIN comments ON comments.post_id = id”(非常需要),用于该:include选项的相同形式的命名关联,它将对关联的表执行INNER JOIN,或者包含两个字符串的混合数组和命名的协会。

如果该值为字符串,则记录将以只读方式返回,因为它们将具有与表的列不对应的属性。传递 :readonly => false以覆盖。



4

好消息,Rails 5现在支持LEFT OUTER JOIN。您的查询现在看起来像:

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

0
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")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.