2011-02-23 104 views
6

Moin,Rails 3:Relation.count和Relation.ount.count之間的區別

我偶然發現了ActiveRecord中的不一致。
我試圖在大表的兩列中獲取所有使用的值組合。 第一個想法:

SELECT DISTINCT col1, col2 FROM table 

試想組織餐作爲模型一個滑軌應用程序和各餐has_many :noodles 每個面具有的屬性(以及因此DB表列)colorshape。 我的目標是獲得所有組合的colorshape的單一餐的數量。

由於AR不提供「不同的」方法I中使用

my_meal.noodles.select("distinct color, shape") 

,得到了(在軌道控制檯STDOUT)8個對象(其分別字符串表示)的六行輸出。但是:

>> my_meal.noodles.select("distinct color, shape").count 
=> 1606 

實際上my_meal含有1606條麪條。 如果我將關係轉換爲數組並獲取它的大小或使用.all.count結果是正確的。

所以我的問題是,爲什麼AR輸出8個對象,但計數所有的DB線?

類似的問題seems to be mentioned here但沒有給出答案。

感謝和問候, 添

+0

是否會調查正在發生什麼SQL,並張貼在這裏?這將存儲在'log/development.log'中,通常非常有用。 – tadman

+0

爲了更深入地嘗試'to_sql':'my_meal.noodles.select(「distinct color,shape」)。count.to_sql'。 – fl00r

+0

其實我剛剛嘗試過相同的測試,在我的情況下一切正常。伯爵已經完成了它的工作 – fl00r

回答

12

好了,感謝tadman推我在正確的方向。

我挖略深(尤其是在日誌文件)和我發現有點怪異。

問題是由選定列的數量引起的。如果一個人只選擇一列,計算結果

my_meal.noodles.select("distinct color").count 

的ActiveRecord創建下列SQL語句:

SELECT COUNT(distinct color) AS count_id FROM "NOODLES" WHERE ("NOODLES".meal_id = 295) 

如果一個選擇兩個或多個列,並適用count

my_meal.noodles.select("distinct color, shape").count 

ActiveRecord忘記了該選擇子句並創建:

SELECT COUNT(*) AS count_id FROM "NOODLES" WHERE ("NOODLES".meal_id = 295) 

這可能是正確的,因爲(SQL的)COUNT只允許一個或更少的列作爲參數。添加countgroup和什麼是好的:

my_meal.noodles.select("distinct color, shape").group("color, shape").count 

SELECT COUNT(*) AS count_all, color, shape AS color_shape FROM "NOODLES" WHERE ("NOODLES".meal_id = 295) GROUP BY color, shape 

除此之外AS color_shape它是精確的我所期待的。但...只有它返回這個:

>> my_meal.noodles.select("distinct color, shape").group("color, shape").count 
=> {star=>309, circle=>111, spaghetti=>189, square=>194, triangle=>179, bowtie=>301, shell=>93, letter=>230} 

>> my_meal.noodles.select("distinct color, shape").group("color, shape").count.class 
=> ActiveSupport::OrderedHash 

這怪異返回值是(除了順序依賴於DB)與

my_meal.noodles.group("shape").count 

結論的結果和返回值相同:
作爲pointed out here有仍然是關係之間的差距(可能他們是數學或關係)和ActiveRecord :: Relations。
我可以看到儘可能頻繁地在模型模式中按結果的優點(至少在Rails應用程序的上下文中)。
但是,真正的關係不是幾個操作的組合的結果,而是這些操作的級聯的結果。 一般來說,ActiveRecord :: Relations的可鏈接性是一件好事,但有一些設計決策我不能遵循。
如果你不能確定每一個行爲都會返回一個新的關係,那麼它就會失去它的許多吸引力。

至於我的問題的解決方案,我將用上述group解決方案和某種骯髒的解決辦法,爲計數操作:

my_meal.noodles.select("distinct color, shape").group("color, shape").all.count 

這將壓縮的結果,在可接受的最小拉力在他們面前從數據庫中移出並創建昂貴的對象來計算它們。或者可以使用手寫的SQL查詢,但爲什麼有一個Rails並不使用它,呵? ;-)

感謝您的幫助,