[英]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.