如何在特定条件后对特定列求和(Postgres)

Posted

技术标签:

【中文标题】如何在特定条件后对特定列求和(Postgres)【英文标题】:How to sum a specific column after a specific criteria (Postgres) 【发布时间】:2020-07-29 16:13:41 【问题描述】:

我有这个代码

SELECT s.name AS School,
        count(distinct u.id) filter (where ut.app_name = 'A' or ut.app_name = 'G') AS A,
        count(distinct u.id) filter (where ut.app_name = 'B' or ut.app_name = 'J') AS B,
        count(distinct u.id) filter (where ut.app_name = 'C') AS C,
        count(distinct u.id) filter (where ut.app_name = 'D') AS D
FROM "public"."user_tokens" ut JOIN
     "public"."users" u
      ON ut.user_id = u.id JOIN
      "public"."user_roles" ur
      ON ut.user_id = ur.user_id JOIN
      "public"."roles" r
      ON ur.role_id = r.id JOIN
      "public"."schools" s
      ON ur.school_id = s.id
GROUP BY s.name
having count(distinct u.id) filter (where ut.app_name = 'A' or ut.app_name = 'G') > 0
    and count(distinct u.id) filter (where ut.app_name = 'B' or ut.app_name = 'J') > 0
    and count(distinct u.id) filter (where ut.app_name = 'C') > 0

上面代码的结果是

School      A       B       C       D
------------------------------------------
P           5       3       2       5
S           1       4       4       9
T           2       3       5       2
U           2       1       3       1

我想对 A 列求和,因此预期结果将是 10。任何启示如何做到这一点?谢谢。

【问题讨论】:

请参阅postgresql.org/docs/current/queries-table-expressions.html 了解分组集。具体来说,rollup 就是你想要的。 其余列会怎样? 您想要单行作为结果还是现有结果加上新列? 我想要一个结果。刚刚尝试了像Select sum(A) FROM (.... 这样的子查询,它起作用了 【参考方案1】:

您已经找到了解决方案,正如您在评论中所写,这只是为了展示如何使用别名而不是在 HAVING 中重复计算:

select sum(A)
from
 (
    SELECT s.name AS School,
            count(distinct u.id) filter (where ut.app_name = 'A' or ut.app_name = 'G') AS A,
            count(distinct u.id) filter (where ut.app_name = 'B' or ut.app_name = 'J') AS B,
            count(distinct u.id) filter (where ut.app_name = 'C') AS C,
            count(distinct u.id) filter (where ut.app_name = 'D') AS D -- can be removed, not used
    FROM "public"."user_tokens" ut JOIN
         "public"."users" u
          ON ut.user_id = u.id JOIN
          "public"."user_roles" ur
          ON ut.user_id = ur.user_id JOIN
          "public"."roles" r
          ON ur.role_id = r.id JOIN
          "public"."schools" s
          ON ur.school_id = s.id
    GROUP BY s.name
 ) as dt
where A> 0
  and B > 0
  and C > 0

【讨论】:

这个 where 子句是否只适用于子查询?如果它不是子查询,我可以使用它还是使用having子句? 别名只能在 ORDER BY 中使用(至少在标准 SQL 中),因为 Select 列表是在 之后 FROM/WHERE/GROUP BY/HAVING 计算的,因此您必须重复 HAVING 中的计数。但是在子查询(派生表)或公用表表达式/CTE 中分配的别名可以在外部 Select 中使用(有一组新的 WHERE/GROUP BY/HAVING),这很方便避免像巨大的 CASE 一样复制代码。

以上是关于如何在特定条件后对特定列求和(Postgres)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Postgres 中对数组列使用 BETWEEN 条件?

过滤后如何对特定列求和

如何对数据表中特定数据列的值求和

如何通过使用 Python 对特定列进行分组来求和?

awk 按列对特定组求和

如何对特定列中具有相同值的行求和