【问题标题】:Adding a SUM group by into a COUNT DISTINCT query将 SUM 组添加到 COUNT DISTINCT 查询中
【发布时间】:2021-11-14 03:39:24
【问题描述】:

我有以下 SQL 查询来计算标签低于某个阈值的不同测验。

SELECT
  COUNT(DISTINCT "quizzes"."id")
FROM
  "quizzes"
  INNER JOIN "sessions" ON "sessions"."id" = "quizzes"."session_id"
  INNER JOIN "subscriptions" ON "subscriptions"."id" = "sessions"."subscription_id"
  LEFT OUTER JOIN "quiz_answers" ON "quiz_answers"."quiz_id" = "quizzes"."id"
  LEFT OUTER JOIN "answers" ON "answers"."id" = "quiz_answers"."answer_id"
  LEFT OUTER JOIN "tag_scores" ON "tag_scores"."answer_id" = "answers"."id"
  LEFT OUTER JOIN "tags" ON "tags"."id" = "tag_scores"."tag_id"
WHERE
  (subscriptions.state = 'subscribed')
  AND (
    tags.id = 56
    and score <= 10
  );

score 是同一测验下存在的同一标签的总和。

我希望能够在查询中添加如下内容:

SUM(tag_scores.score) group by tags.id, quizzes.id AS score

这样分数不是根据特定标签分数计算的,而是根据tags.idquizzes.id 分组的相同标签的总和计算的。

输出应该只是结果的计数。

我很难将其添加到查询中。

任何想法或提示如何继续?

【问题讨论】:

  • 我们能否看到一些示例数据及其预期输出?
  • 我故意避免添加样本数据,因为所有的关节,这会导致不必要的混乱。与上述示例相关的是,分数应从tag_scores.score 求和,并按tags.idquizzes.id 分组。结果应该只是找到的行数。
  • count(*) 给出行数。那不行吗?
  • 我发布的查询工作。但它缺少SUM(tag_scores.score) group by tags.id, quizzes.id AS score 部分,我不知道在哪里输入查询。
  • group by tags.id, quizzes.id 不同意发出单个 COUNT(DISTINCT "quizzes"."id")。如果您将tags.id 添加到输出中,可能会有意义。但你不希望那样。那么您是否要分别强制每个包含的 tag.id 的总和低于 10?请解释一下。

标签: sql postgresql


【解决方案1】:

应该这样做:

SELECT count(*)
FROM   quizzes q
JOIN   LATERAL (
   SELECT SUM(ts.score) AS sum_score
   FROM   quiz_answers qa
   JOIN   answers      a  ON a.id = qa.answer_id
   JOIN   tag_scores   ts ON ts.answer_id = a.id
-- JOIN   tags         t  ON t.id = ts.tag_id  -- not needed
   WHERE  qa.quiz_id = q.id
   AND    ts.tag_id = 56
   ) AS score56 ON score56.sum_score <= 10
WHERE  EXISTS (
   SELECT FROM sessions se
   JOIN   subscriptions su ON su.id = se.subscription_id
   WHERE  se.id = q.session_id
   AND    su.state = 'subscribed'
   );

LATERAL 连接强制执行您想要的附加过滤器。测验被淘汰...

  • 根本没有连接tag_id 56(那么sum_score就是NULL)。
  • 或标签 56 的所有分数之和 > 10。

LATERAL 对子集有意义(当WHERE EXISTS ... 实际上过滤多于几行时)。否则,all 答案标签上的普通子查询更便宜。

由于我们不将主表quizzes 中的行与连接相乘,因此我们也不需要昂贵的count(DISTINCT ...)。一个简单的count(*) 现在就可以了。

我将您的原始过滤器移至 EXISTS 表达式,因为我不知道这些连接是否可以乘以行。如果 sessionssubscriptionsquizzes 处于 1:1 关系,那么您可以保留这些原始连接。

【讨论】:

  • 哇!很好的查询,我会在以后学习。但是,我收到了ERROR: column score56.score does not exist
  • @Martin:注意修复。缺少列别名。
  • 漂亮!非常感谢您的帮助,当您遇到合适的人时,总是对互联网带来的力量感到惊讶。
  • 我注意到当多个 JOIN LATERAL 出现在不同标签中搜索分数时,有时使用 OR 查询会呈指数级增长:pastebin.com/pz87d4HC。有什么办法可以预防吗?
  • @Martin:您也许可以在一个横向子查询中完成所有操作。用详细信息开始一个新问题。
猜你喜欢
  • 2019-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-12
  • 1970-01-01
  • 2014-12-31
  • 2016-05-06
  • 1970-01-01
相关资源
最近更新 更多