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

时间:2011-11-06 05:34:10

标签: ruby-on-rails ruby activerecord

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

Model1: GROUP(id, name)
Model2: USER_GROUP_CMB(id, user_id, group_id)

预期的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

我尝试在下面设置关联,但我不知道在此之后该怎么做。

class Group < ActiveRecord::Base
  has_many :user_group_cmb
end

class UserGroupCmb < ActiveRecord::Base
  has_many :group
end

Rails版本:3.1.1

8 个答案:

答案 0 :(得分:32)

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

Group.includes(:user_group_cmb).where(user_group_cmbs: { user_id: 1 })

答案 1 :(得分:14)

Rails 5+允许您执行以下操作:

Group.left_outer_joins(:user_group_cmb)

http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-left_joins

答案 2 :(得分:10)

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

Group.eager_load(:user_group_cmb)

...它将执行左外联接

答案 3 :(得分:8)

提及using includes可能有不良副作用可能非常重要。

  

如果过滤后的关联随后是作用域,则全部   原始过滤消失

     

事实证明,通过确定过滤后的关联,我们已经失去了任何   我们从包含的过滤作为副作用。事实并非如此   因为我们如何搜索。

请务必阅读完整的文章,或者a gem for that

答案 4 :(得分:7)

使用自定义联接声明:

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

答案 5 :(得分:6)

接受答案的问题是它实际上会在技术上执行LEFT INNER JOIN,因为它不会显示user_group_cmbs. user_id为空的条目(这是做{{1}的原因}})。

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

LEFT OUTER JOIN

或者更方便的#eager_load

Group.includes(:user_group_cmb).references(:user_group_cmb)

阅读更详细的解释here

答案 6 :(得分:2)

如果您只需要将用户链接到群组,请使用has_and_belongs_to_many。如果您需要存储其他会员信息,请使用has_many :through

示例:

class User < ActiveRecord::Base
  has_and_belongs_to_many :groups
end

class Group < ActiveRecord::Base
  has_and_belongs_to_many :users      
end

答案 7 :(得分:0)

无法对之前的答案发表评论,因为我没有50的声誉。 但是当我遇到以下错误

时,这就是我的工作方式
  

包含引用的关系会引发一个StatementInvalid异常,抱怨它错过了一个FROM子句条目。我需要添加一个显式调用join,默认为inner。

我必须使用.references并提及表名或将其添加到FROM子句