2011-03-30 70 views
1

如何在ActiveRecord中指定JOIN ON子句?Activerecord:包含附加條件

對ActiveRecord.find方法使用:include參數時,創建的SQL使用JOIN操作和外鍵=主鍵的ON子句。例如:

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和乙

這不起作用

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 

回答

-1

這可能不是最Railistic解決方案,但我覺得很方便,當我在尋找Railstic sulutions的絕望。

我相信你可以找出如何處理下面的例子,並希望你能以某種方式發現它有用。

@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') 
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執行它,並處理,使單一的查詢是非常重要的直接結果。