Assumpti附加組件:
- 你確實有一個數字列在您的評級模型(任何類型的SQL的
AVG
是罰款)。在我的示例中,我使用了一列ratings.rating
。因爲average_user_score
比較好。
- 你不介意沒有得到沒有任何優惠的用戶:無論如何,他們的平均評分沒有明確定義。
- 你不會偏離Rails的慣例足夠有一個主鍵而不是
id
。
顯示每個用戶的優惠是一項直截了當的任務:在@users.each do |user|
的循環中,您可以做user.offers.each do |offer|
並進行設置。這裏唯一的問題是它會爲每個用戶執行一個單獨的查詢。不好。
「提取報價」部分是一個標準的N + 1計數器,甚至可以看到in the guides。
@users = User.includes(:offers).all
這裏有趣的部分只是獲取平均值。
爲此我打算使用Arel。它已經是Rails的一部分,ActiveRecord建立在它之上,所以你不需要額外安裝任何東西。
你應該能夠做一個加入這樣的:
User.joins(offers: :ratings)
這樣就不會(從過濾那些沒有爲用戶提供了除)給你什麼有趣的事。在內部,你會得到一個巨大的每一個評級加入相應的報價和該報價的用戶。由於我們採用的是平均每位用戶,因此我們需要group byusers.id
,有效地爲每個users.id
值創建一個條目。也就是說,每個用戶一個。用戶列表,是的!
讓我們停下來等一下,做一些分配讓Arel相關的代碼更漂亮。其實我們只需要兩個:
users = User.arel_table
ratings = Rating.arel_table
好的。所以。我們需要獲取用戶列表(所有字段),併爲每個用戶獲取他的優惠評分'rating
「字段中顯示的平均值。因此,讓我們來撰寫這些SQL表達式:
# users.*
user_fields = users[Arel.star] # Arel.star is a portable SQL "wildcard"
# AVG(ratings.rating) AS average_user_score
average_user_score = ratings[:rating].average.as('average_user_score')
所有設置。準備好最終查詢:
User.includes(:offers) # N+1 counteraction
.joins(offers: :ratings) # dat join
.select(user_fields, average_user_score) # fields we need
.group(users[:id]) # grouping to only get one row per user
請添加相關欄目。 –
我真的不知道該怎麼做,這就是爲什麼我沒有發表我的例子,我正在尋找一個人,至少讓我指向正確的方向。 – MatthewK
如果沒有至少需要@juergend要求的信息,我們無法幫助您。哪一列是評分表上的分數?你的外鍵是什麼? –