如何正确使用 sum (case ... when ... then ...)?

How to use sum (case ... when ... then ...) properly?

我想将具有特定值的行汇总为特定列。 早些时候我做了这样的事情:

SELECT date                                          AS 'Date',
   sum(CASE license_id WHEN 'a' THEN data.Amount ELSE 0 END) AS 'a',
   sum(CASE license_id WHEN 'b' THEN data.Amount ELSE 0 END) AS 'b',
   sum(
           CASE license_id WHEN '1' THEN data.Amount ELSE 0 END +
           CASE license_id WHEN '2' THEN data.Amount ELSE 0 END +
           CASE license_id WHEN '3' THEN data.Amount ELSE 0 END
       )                                                        AS 'c',
   sum(
           CASE license_id WHEN '10' THEN data.Amount ELSE 0 END +
           CASE license_id WHEN '11' THEN data.Amount ELSE 0 END +
           CASE license_id WHEN '12' THEN data.Amount ELSE 0 END
       )                                                        AS 'd'
FROM ...
...

这正是我想要的,但现在我有了一个新场景。 我需要总结不同的临时结果。以下代码不起作用,只是为了解释我想要的东西:

SELECT date                                          AS 'Date',
   sum(CASE license_id WHEN 'b' THEN data.Amount ELSE 0 END) AS 'b',
   sum(    CASE license_id WHEN '1' THEN data.Amount ELSE 0 END +
           CASE license_id WHEN '2' THEN data.Amount ELSE 0 END +
           CASE license_id WHEN '3' THEN data.Amount ELSE 0 END +
           b
       )                                                        AS 'c',
FROM ...
...

所以我的问题是因为这只是整个SELECT-声明的一部分:

提前感谢您的帮助!

因为您总是测试 license_id 并且总是求和 data.Amount 那么 IN 条件会节省您大量的输入:

 SELECT
      sum(CASE license_id WHEN 'a' THEN data.Amount END) AS a,
      sum(CASE license_id WHEN 'b' THEN data.Amount END) AS b,
      sum(CASE WHEN license_id IN ('b','1','2','3') THEN data.amount END) as c
      ...

你没有指定你使用的是哪个 RDBMS,但我敢打赌,如果它支持 CASE 表达式,那么它可能也支持 IN.

问题是 b 不被理解——或者至多是对 table 中列的引用而不是您的表达式。

这是SQL的一般属性。您不能在同一查询的 SELECTFROMWHERE 子句中重复使用列别名。 MySQL:

中基本上有三个选项
  • 使用子查询
  • 重复表达式
  • 使用 CTE

在这种情况下,实际上还有第四种选择,因为重写查询可以简化逻辑:

select date,
       sum(case license_id when 'b' then data.Amount else 0 end) AS b,
       sum(case when license_id in ('b', '1', '2', '3')  then data.Amount else 0 
           end) as c,
from ...

请注意 case 的形式略有不同,其中布尔条件位于 when 之后。

此外,列别名不需要单引号。如果您想防止代码中出现问题,请仅对字符串和日期常量使用单引号。