【问题标题】:SQL: Sum the results of a query by groupSQL:按组对查询结果求和
【发布时间】:2016-01-04 09:38:16
【问题描述】:

几天前我刚开始学习 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 值 ______________________ 1 10 2 5 1 34.5 2 45 1 6 2 3

如果您知道执行此操作的方法,或者是否有其他我应该研究的方法,请告诉我。

('likes' 'reviews' 和 'progress' 表都包含字段“training_id”。您如何看待加入三个表开始?)

【问题讨论】:

  • 跑步前先走吧
  • 您实际使用的是什么数据库?期望的输出是什么?
  • 为什么不对所有值使用 SUM() 函数?
  • 发布一些示例数据。
  • 问题标记为 mysql、sql-server 和 sqlite。您实际使用的是哪个?

标签: mysql sql sql-server sqlite


【解决方案1】:

这令人印象深刻。您的查询结构良好且易于阅读。如果您想要每个 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;

【讨论】:

    【解决方案2】:

    好的,谢谢您的意见。我的第二个预感是对的。我需要使用联接。我只在文档中阅读了有关 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-20
      • 2012-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-28
      相关资源
      最近更新 更多