2015-07-20 151 views
0

我遇到了一個查詢問題。 讓我解釋一下我想要的東西: 對於bravity的緣故,讓我們說,我有三個表:帶有聯接的SQL複雜查詢

-Offers

-Ratings

-Users

現在我想做的事是要創建SQL查詢:

  1. 我希望列出其所有字段和附加臨時列這並不是存儲在任何稱爲AverageUserScore的地方。

  2. 此AverageUserScore是抓取屬於特定用戶的所有優惠的產品,然後抓取屬於這些優惠的所有評分,然後評估這些評分的平均值 - 此平均分爲AverageUserScore。

要進一步解釋它,我需要這個查詢Ruby on Rails應用程序。在瀏覽器內部應用程序中,您可以看到其他用戶的所有優惠,其中AverageUserScore作爲最後一列。

協會:

  1. 發售有許多收視率
  2. 發售屬於用戶
  3. 評級屬於提供
  4. 用戶有很多的優惠
+0

請添加相關欄目。 –

+0

我真的不知道該怎麼做,這就是爲什麼我沒有發表我的例子,我正在尋找一個人,至少讓我指向正確的方向。 – MatthewK

+0

如果沒有至少需要@juergend要求的信息,我們無法幫助您。哪一列是評分表上的分數?你的外鍵是什麼? –

回答

2

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