2015-10-07 105 views
-2

我剛剛開始學習SQL,前幾天我正在處理一些基本示例。在這個例子中,我想找到我的朋友和隊友喜歡的訓練(根據我的朋友中有多少人喜歡訓練,有多少朋友完成了訓練,以及我的朋友在訓練中的平均評分)。到目前爲止,我使用子查詢爲每個訓練的每種加權值賦予一個加權值。我想總結每次訓練的加權值,每次訓練總數,然後按總數排序訓練列表,並從中選出前幾名。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 

請讓我知道,如果你知道的方式做到這一點,或者如果有這種方法,我應該尋找一種替代方法。

(表「喜歡」「評論」和「進步」都包含字段「training_id」。你想想加入三個表開始與什麼?)

+0

可能的字段名走前跑步 – Strawberry

+2

你實際使用的數據庫是什麼?什麼是期望的輸出? –

+0

爲什麼不使用SUM()函數來處理所有的值? –

回答

0

這是相當可觀的。您的查詢結構合理,易於閱讀。如果你想每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×3×4 = 24箇中間記錄)。在您的具體情況下,這不會造成任何損害,因爲AVG會導致相同的值,並且您會用COUNT(DISTINCT progress_id)COUNT(DISTINCT likes_id)替換COUNT(*),但是一旦您使用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; 
0

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

以下是解決方案。

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,總有一露苗頭的結果
1,初級LiveCode,53
2,SQL 101,48