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

Posted

技术标签:

【中文标题】如何正确使用 sum (case ... when ... then ...)?【英文标题】:How to use sum (case ... when ... then ...) properly? 【发布时间】:2019-09-12 17:01:44 【问题描述】:

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

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 语句的一部分:

我可以让CASE ... WHEN ... THEN ... + CASE ... WHEN ... THEN ... + CASE ... WHEN ... THEN ... 更简单吗? 是否有可能实现我可以在进一步计算中使用临时结果?

提前感谢您的帮助!

【问题讨论】:

能否提供表格结构、示例输入数据和示例结果行?每个案例末尾的+ 是做什么用的? 首先,您可以删除部分ELSE 0,因为它默认为null,即未添加。 使用一种情况,而不是把几种情况相加。 另外,您可以使用IN,如CASE license_id IN ('1', '2', '3') THEN ... 您使用的是哪个DBMS 产品? “SQL”只是一种查询语言,而不是特定数据库产品的名称(并且您使用的是无效的标准 SQL)。请为您正在使用的数据库产品添加tag 【参考方案1】:

问题是 b 不被理解 - 或者充其量是对表中列的引用而不是您的表达式。

这是 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 之后是一个布尔条件。

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

【讨论】:

"或 最好 引用列 ...",我会说相反,“或 最差 引用一列……”。 非常感谢您的建议,但我担心这不会解决我的问题。是否可以有像 @var = ('1', '2', '3') 之类的变量? @DerKnecht 。 . .这(以及其他答案)回答了您提出的问题。如果您有不同的问题,那么也许您应该将其作为 问题提出。【参考方案2】:

由于您总是在测试 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

【讨论】:

谢谢@TheImpaler 我已经摆脱了我的copypasta示例。 @TheImpaler,取决于您是否希望不存在的 license_id 为 0 或 null。 @TheImpaler, dbfiddle.uk/… @jarlh 圣鳄梨酱。你说的对。我在 PostgreSQL、MariaDB、DB2、Oracle 和 MySQL 中测试了您的示例。

以上是关于如何正确使用 sum (case ... when ... then ...)?的主要内容,如果未能解决你的问题,请参考以下文章