如何在ActiveRecord中指定JOIN ON子句?
对ActiveRecord.find方法使用:include参数时,创建的SQL使用带有foreign key = primary key的ON子句的JOIN操作。例如:
A.find(:include => :B)
结果
select ... from A
left outer join B on B.a_id=A.id
现在我的例子:
A.find(:include => { :B => { :include => :C } } )
结果:
select ... from A
left outer join B on B.a_id=A.id
left outer join C on C.b_id=B.id
但是,我只想要C中的一些记录,但如果没有找到,那么我仍然想要A和B
这不起作用
A.find(:include => { :B => { :include => :C } },
:condition => "C.rec<10" )
因为这导致:
select ... from A
left outer join B on B.a_id=A.id
left outer join C on C.b_id=B.id
where C.rec<10
如何指示AcriveRecord创建这样的查询?
select ... from A
left outer join B on B.a_id=A.id
left outer join C on C.b_id=B.id and C.rec<10
答案 0 :(得分:1)
我不知道用关联方法添加ON子句的方法。
对于您的示例,仅在C中仅加载一些记录的最简单方法是在B中定义与条件的关联。(请参阅此ActiveRecord::Associations API documentation的“关联的加载加载”部分。)
class A < ActiveRecord::Base
has_many :bs
end
class B < ActiveRecord::Base
has_many :cs
has_many :cs_with_rec_less_than_10, :class_name => 'C', :conditions => ['rec < 10']
end
class C < ActiveRecord::Base
end
您可以致电:
A.includes(:bs => :cs_with_rec_less_than_10)
这将生成3个查询,每个表一个,而不是在1个查询中加入它们。例如,如果A和B各包含2个ID为1和2的记录:
SELECT "as".* FROM "as"
SELECT "bs".* FROM "bs" WHERE ("bs".a_id IN (1,2))
SELECT "cs".* FROM "cs" WHERE ("cs".b_id IN (1,2) AND (rec < 10))
如果使用左连接进行单个查询很重要,我会手动编写查询,使用ActiveRecord::Base.connection.execute
执行查询,并直接处理结果。
答案 1 :(得分:-1)
这可能不是最具铁路性的解决方案,但是当我绝望地寻找Railstic风暴时,我发现它很方便。
我相信你可以弄清楚如何处理以下示例,并希望你能以某种方式发现它有用。
@visits = Visit.select("v.*, c.*" ).
where("u.id = ?", session[:user_id]).
joins( %{ as v inner join customers as c on (v.customer_id = c.id)
inner join businesses as b on (v.business_id = b.id)
inner join managers as m on (b.manager_id = m.id)
inner join users as u on (m.user_id = u.id)
} ).
order(' v.created_at DESC')