我几天前刚刚开始学习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 :(得分: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 x 3 x 4 = 24个中间记录)。在您的具体情况下,这不会造成任何损害,因为AVG
会产生相同的价值,并且您将COUNT(*)
替换为COUNT(DISTINCT progress_id)
和COUNT(DISTINCT likes_id)
,但一旦您和#39;使用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;
答案 1 :(得分:0)
好的,谢谢你的意见。我第二次预感是正确的。我需要使用联接。我只阅读了文档中的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