如何使用Rails ActiveRecord进行LEFT OUTER JOIN?

zon*_*ono 21 ruby activerecord ruby-on-rails

我没有任何想法.你能给我任何线索(比如参考站点).任何帮助将不胜感激.

Model1: GROUP(id, name)
Model2: USER_GROUP_CMB(id, user_id, group_id)
Run Code Online (Sandbox Code Playgroud)

预期的SQL语句:

SELECT * 
FROM groups AS g LEFT OUTER JOIN user_group_cmbs AS cmb 
            ON g.id = cmb.group_id
WHERE cmb.user_id = 1
Run Code Online (Sandbox Code Playgroud)

我尝试在下面建立协会,但我不知道在此之后该怎么办.

class Group < ActiveRecord::Base
  has_many :user_group_cmb
end

class UserGroupCmb < ActiveRecord::Base
  has_many :group
end
Run Code Online (Sandbox Code Playgroud)

Rails版本:3.1.1

Rya*_*igg 33

我相信如果您在关联使用的表上执行条件,includes则将使用LEFT OUTER JOIN查询includes:

Group.includes(:user_group_cmb).where(user_group_cmbs: { user_id: 1 })
Run Code Online (Sandbox Code Playgroud)

  • 在这里不起作用(Rails 3.2.7):在`includes`引用的关系上使用一个条件会引发一个`StatementInvalid`异常,抱怨它错过了一个`FROM-clause条目`.我需要添加一个显式调用`join`,默认为内部. (7认同)
  • 如果你真的讨厌字符串,喜欢符号和哈希(不是火箭),你可以做```Group.includes(:user_group_cmb).where(user_group_cmbs:{user_id:1})``` (2认同)

kno*_*opx 10

您可以在rails 3.x中执行此操作,无论您是否在where子句中引用该表:

Group.eager_load(:user_group_cmb)
Run Code Online (Sandbox Code Playgroud)

......它将执行左外连接


小智 8

提及使用包含可能有不良副作用可能是非常重要的.

如果过滤后的关联随后作用域,则所有原始过滤消失

事实证明,通过对过滤后的关联进行确定,我们已经失去了从包含中获得的任何过滤副作用.而且这也不是因为我们如何搜索.

一定要阅读完整的文章,或者有一个宝石.


ham*_*ady 7

使用自定义连接语句:

Group.joins("left outer join user_group_cmbs as cmb on groups.id = cmb.group_id")
  .where("cmb.user_id = ?", 1)
Run Code Online (Sandbox Code Playgroud)


KAR*_*ván 6

接受的答案的问题是它实际上会在LEFT INNER JOIN技术上做,因为它不会显示user_group_cmbs. user_idnull为空的条目(这是做a的原因LEFT OUTER JOIN).

一个有效的解决方案是使用#references:

Group.includes(:user_group_cmb).references(:user_group_cmb)
Run Code Online (Sandbox Code Playgroud)

或者更方便#eager_load:

Group.eager_load(:user_group_cmb)
Run Code Online (Sandbox Code Playgroud)

请在此处阅读更详细的说明.