簡體   English   中英

SQL:按組匯總查詢結果

[英]SQL: Sum the results of a query by group

幾天前我剛剛開始學習 SQL,我正在研究一些基本的例子。 在這個例子中,我想找到我的朋友和隊友喜歡的訓練(基於我有多少朋友喜歡訓練,有多少朋友完成了訓練,以及我的朋友對訓練的平均評分)。 到目前為止,我使用子查詢為每次訓練的每種類型的加權值獲取加權值。 我想對每個訓練的加權值求和,給每個訓練一個總數,然后按總數對訓練列表進行排序,並從中選擇前幾個。

這是我所做的。

SELECT training_id, (5* COUNT()) AS [value]FROM progress
WHERE user_id IN (SELECT friend_id AS user_ids FROM friendships WHERE user_id=6 UNION SELECT user_id FROM membership WHERE team_id IN (SELECT team_id FROM membership WHERE user_id = 6))
AND completed = 1
GROUP BY training_id

UNION ALL

SELECT training_id, (10 * AVG(rating))
FROM reviews
WHERE user_id IN (SELECT friend_id AS user_ids FROM friendships WHERE user_id=6 UNION SELECT user_id FROM membership WHERE team_id IN (SELECT team_id FROM membership WHERE user_id = 6))
GROUP BY training_id

UNION ALL

SELECT training_id, COUNT()
FROM likes
WHERE user_id IN (SELECT friend_id AS user_ids FROM friendships WHERE user_id=6 UNION SELECT user_id FROM membership WHERE team_id IN (SELECT team_id FROM membership WHERE user_id = 6))
GROUP BY training_id

結果如下:

training_id     value
______________________
1                10
2                5
1                34.5
2                45
1                6
2                3

如果您知道這樣做的方法,或者是否有我應該考慮的替代方法,請告訴我。

(表'likes' 'reviews' 和'progress' 都包含字段“training_id”。你怎么看待加入這三個表開始?)

這相當令人印象深刻。 您的查詢結構良好且易於閱讀。 如果您想要每個 training_id 的總和,只需自己構建一個外部查詢:

select training_id, sum(value)
from (<your query here>) x
group by training_id
order by sum(value) desc;

至於加入表格:不,通常你不想這樣做。 您不想將每條進度記錄與每條評論記錄和每條training_id 的每條喜歡記錄連接起來。 這將使您的值成倍增加(例如,一次培訓的 2 個進度條目、3 條評論和 4 個贊將為您提供 2 x 3 x 4 = 24 條中間記錄)。 在您的特定情況下,這不會有什么害處,因為AVG會產生相同的值,您可以將COUNT(*)替換為COUNT(DISTINCT progress_id)COUNT(DISTINCT likes_id) ,但是一旦您使用SUM您就會麻煩。

你可以做的是加入聚合:

with mates as
(
  select friend_id as user_id from friendships where user_id = 6
  union 
  select user_id from membership where team_id in 
               (select team_id from membership where user_id = 6)
)
select 
  training_id, 
  coalesce(p.value, 0) + 
  coalesce(r.value, 0) + 
  coalesce(l.value, 0) as total
from
(
  select training_id, 5 * count(*) as value
  from progress
  where user_id in (select user_id from mates)
  and completed = 1
  group by training_id
) p
full outer join
(
  select training_id, 10 * avg(rating) as value
  from reviews
  where user_id in (select user_id from mates)
  group by training_id
) r using (training_id)
full outer join
(
  select training_id, count(*) as value
  from likes
  where user_id in (select user_id from mates)
  group by training_id
) l using (training_id)
order by 2 desc;

好的,感謝您的輸入。 我的第二個預感是對的。 我需要使用連接。 我只在文檔中閱讀了 Joins 並且不熟悉它們,但是一旦我嘗試過它,它就非常簡單。

這是解決方案。

SELECT training.*, ((10 * AVG(reviews.rating)) + COUNT(DISTINCT likes.user_id) + ( 5* COUNT(DISTINCT progress.trainee_id))) AS total FROM training JOIN likes ON training.training_id = likes.training_id JOIN reviews ON training.training_id = reviews.training_id JOIN progress ON training.training_id = progress.training_id WHERE user_id IN (SELECT friend_id AS user_ids FROM friendships WHERE user_id=6 UNION SELECT user_id FROM membership WHERE team_id IN (SELECT team_id FROM membership WHERE user_id = 6)) AND progress.completed = 1 AND progress.trainee_id IN (SELECT friend_id AS user_ids FROM friendships WHERE user_id=6 UNION SELECT user_id FROM membership WHERE team_id IN (SELECT team_id FROM membership WHERE user_id = 6)) ORDER BY total DESC GROUP BY training_name LIMIT 6

這給了我
training_id, training_name, total -- 這些是結果的字段名
1、初學者LiveCode,53
2、SQL 101、48

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM