2016-01-27 46 views
0

我目前正在嘗試編寫一個工作人員,必須檢查最新的孩子的狀態,並根據它排隊。例如,發現父母的最大的孩子是在學校Rails ActiveRecord加入最新的孩子的範圍

class Parent 
    has_many :children 
end 
class Child 
    belongs_to :parent 
    lookup_for :status, symbolize: true 
end 

目前我的範圍是:

Parent.joins(:children). 
     where("children.birth_date = 
      (SELECT MAX(children.birth_date) 
      FROM children 
      WHERE children.parent_id = parents.parent_id"). 
     where('children.status = ?', Status[:in_school]').pluck(:parent_id) 

好像應該有更好的方式來做到這一點。任何想法

要澄清我找所有誰是最古老的父母的孩子還在上學

+0

當然,你的意思是「parents.id」,而不是:上述模式中的parent_id?我的意思是,你可以這樣做,但接近通用的標準只是主鍵的「id」。 – Rob

+0

我建議你檢查這個stackoverflow後:[http://stackoverflow.com/questions/1313120/retrieving-the-last-record-in-each-group](http://stackoverflow.com/questions/1313120/retrieving - 最後記錄在每個組) –

+0

是啊,一般我同意,但在數據庫中,我們使用它實際上是在像父母形式.parents_id – tuxr

回答

0

如果您使用的是第一和/或最後一個孩子很多在查詢中,我將他們加爲場在父

class Parent 
    belongs_to :youngest_child, class_name: Child, inverse_of: :parent 
end 
0

好了,你可以把一些邏輯到像下面的連接()語句,但我看不出你如何能夠擺脫必須有一個子查詢的地方。

Parent.joins(%Q{left join children on children.parent_id = parents.id 
        and children.birth_date = (select max(birth_date) from children 
        where children.parent_id = parents.id)}). 
       where('children.status = ?', Status[:in_school]') 

那看起來就像那樣。 HTH

0

或者,您可以使用order和last來查找最後一個孩子,然後檢查內存中孩子的狀態。這種方法最多隻會有一個孩子被提取,所以表現是合理的。如下所示:

child=Child.order(:birth_date).joins(:parent).last 
parent.do_stuff if child.in_school? 
+0

是的,我有其他範圍父母基地,我需要 – tuxr

+0

哦,你需要它從父母進來嗎?我相信我們可以做一個合併,並使其工作,如果這是你所需要的。 – Rob

+0

是的,它需要來自父母,因爲它會被限制更多的加入之前,這使得它更便宜,只需要看看有限的數字或剩餘的父母 – tuxr

0

您的查詢的工作原理 - 它可以完成工作,而且很清楚您要做什麼。我在現在正在處理的應用中對類似關聯進行了測試,並且ActiveRecord將所有查詢合併爲一個查詢,並且它花費了1.4ms

如果你想優化性能,你可以使用一個連接,以獲得最大的孩子,而不是一個子查詢:

Parent.joins("INNER JOIN (
       SELECT c1.* 
       FROM children c1 
       LEFT JOIN children c2 ON (c1.parent_id = c2.parent_id AND c1.birthdate > c2.birthdate) 
       WHERE c2.parent_id IS NULL 
      ) c ON parent.parent_id = c.parent_id") 
       .where('children.status = ?', Status[:in_school]) 
       .pluck(:parent_id) 

這是一個有點不太清楚你要什麼,因爲它使用一種手動外連接,但它也允許嵌套連接使用索引。在與上述相同的測試場景中,這在0.9ms中執行相同的查詢(幾乎快兩倍)。那是一個非常小的數據庫,只有幾百條記錄。擁有數百萬條記錄,差異將是顯而易見的。

感謝這個StackOverflow answer,爲加入模式。