2015-10-07 179 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