2012-03-21 44 views
3

我有一個項目列表,只想顯示有任務的項目。是否有可能使用has_many關係計數的條件?有沒有可能使用has_many關係計數的條件?

# get my project list 
Project.includes(:tasks).where(...) 

class Project < ActiveRecord::Base 
    has_many :tasks 

class Task < ActiveRecord::Base 
    belongs_to :project 

目前我正在通過一個循環,但我不認爲這是正確的方式。

+1

我也問過類似的問題[這裏](http://stackoverflow.com/questions/8227557/activerecord-find-categories-which-contain-at-least-one-item)。希望它也能幫助你。 – ZelluX 2012-03-21 14:22:47

回答

1

由於您已經渴望加載項目的任務,因此可以使用以下語句來獲取具有任務的項目。

# get my project list 
Project.includes(:tasks).where("tasks.id IS NOT NULL") 

這工作,因爲includes使用LEFT OUTER JOIN

另一方面,如果您不想急於加載任務,則可以使用joins,因爲它使用INNER JOIN。

Project.joins(:tasks).where(...) 
1

includes指令通常指示只是以數據庫方式急於加載這些關聯,而不是JOIN,所以如果沒有其他工作,您就無法真正地做到這一點。

縮放比例很好的一種方法是使用關聯的counter_cache功能,因此您始終擁有任務數量的數字計數。您甚至可以在這些上添加索引以進一步提高查詢的性能。

另一種方法是嘗試從tasks表反向工作,也許是這樣的:

Project.where('id IN (SELECT DISTINCT project_id FROM tasks)') 

想必你對project_id指數在tasks表,以一個相當便宜的操作。

+0

你不需要'counter_cache'。由於正在使用'includes'指令,所生成的底層SQL使用了LEFT OUTER JOIN。這是做一個不空檢查的問題。如果用戶使用'joins',場景就簡單多了。我在下面的回答中已經討論過這個問題。 – 2012-03-21 16:35:04

+0

我的心裏最好不要加載你不需要的東西。如果一個項目有kabillion任務,全部加載都沒有限制可能會粉碎應用程序。 – tadman 2012-03-21 19:00:08

+0

我明白,這是在選擇急切加載時必須採取的一般預警。 – 2012-03-21 19:36:39

1

如果問題很簡單,只要標題所暗示的,不知道爲什麼這不會做的伎倆:

Project.joins(:tasks) 

除非另有規定,聯結將內部聯接,從而排除任何結果其項目沒有任務,所以也許這就是你所需要的......如果你想顯示所有項目的任務。

如果你有一些條件(例如,項目狀態爲有效),你也可以指定像

Project.joins(:tasks).where("status = 'active') 

的情況或者有我錯過了什麼?