【问题标题】:Sum rows from different conditions in Mysql在 Mysql 中对不同条件的行求和
【发布时间】:2014-04-25 21:26:53
【问题描述】:

原表很大,我将其简化:

我的表:

CONDITION SIZE 
1          10
9          10
9          10
1          20
9          20
1          20
1          30

查询类似于

SELECT
  CASE WHEN CONDITION=1 THEN 'OK' ELSE 'BAD' END AS Status,
  SUM (CASE WHEN SIZE=10 THEN 1 ELSE 0 END) AS Small,
  SUM (CASE WHEN SIZE=20 THEN 1 ELSE 0 END) AS Medium,
  SUM (CASE WHEN SIZE=30 THEN 1 ELSE 0 END) AS Large,
FROM mytable GROUP BY Status

那么我们就有了这个结果

Status    Small    Medium    Large
OK         1         2         1
BAD        2         1         0

获取的正确代码是什么:

Status    Small    Medium    Large
OK         1         2         1
BAD        2         1         0
TOTAL      3         3         1   

【问题讨论】:

    标签: mysql


    【解决方案1】:

    您可以像这样将WITH ROLLUP 子句添加到您的GROUP BY 条件中:

    SELECT
      CASE WHEN CONDITION=1 THEN 'OK' ELSE 'BAD' END AS Status,
      SUM (CASE WHEN SIZE=10 THEN 1 ELSE 0 END) AS Small,
      SUM (CASE WHEN SIZE=20 THEN 1 ELSE 0 END) AS Medium,
      SUM (CASE WHEN SIZE=30 THEN 1 ELSE 0 END) AS Large,
    FROM mytable
    GROUP BY Status WITH ROLLUP
    

    这将产生如下结果集:

    Status    Small    Medium    Large
    OK         1         2         1
    BAD        2         1         0
    [NULL]     3         3         1 
    

    您需要了解“状态”列中没有任何Total 值的行为。相反,Status 列将具有 NULL 值,指示这是进行汇总的位置。

    有关更多信息,您可以在此处阅读文档:http://dev.mysql.com/doc/refman/5.6/en/group-by-modifiers.html

    【讨论】:

    • 我认为您可以通过将 CASE..END 包装在 COALESCE(CASE..END, 'ALL) AS 状态中来获得 TOTAL。或类似的事情。
    • @KarlKieninger:不完全是,因为查询是按Status 别名分组的,所以这有点递归。如果 GROUP BY 子句被更改为不使用别名,那么这确实是可能的。
    • @eggyal 对。顺便说一句,在 sql server 中,您可以使用 GROUPING 来处理 NULL (stackoverflow.com/questions/18897415/…),但我在 MySQL 中没有找到等效项。
    【解决方案2】:

    如果我理解正确,您需要在总查询中联合,因为您不能同时以不同的方式聚合。

    SELECT
      CASE WHEN CONDITION=1 THEN 'OK' ELSE 'BAD' END AS Status,
      SUM (CASE WHEN SIZE=10 THEN 1 ELSE 0 END) AS Small,
      SUM (CASE WHEN SIZE=20 THEN 1 ELSE 0 END) AS Medium,
      SUM (CASE WHEN SIZE=30 THEN 1 ELSE 0 END) AS Large,
    FROM mytable GROUP BY Status
    
    UNION
    
    SELECT
      'Total' AS Status,
      SUM (CASE WHEN SIZE=10 THEN 1 ELSE 0 END) AS Small,
      SUM (CASE WHEN SIZE=20 THEN 1 ELSE 0 END) AS Medium,
      SUM (CASE WHEN SIZE=30 THEN 1 ELSE 0 END) AS Large,
    FROM mytable
    

    【讨论】:

    • 刚刚测试过,效果很好!谢谢!
    • 有效,但本质上需要两个查询(处理工作量大约翻倍)。
    • 嘿,我不知道汇总。看看我是怎么学到东西的。不确定它在内部是如何工作的,但我希望你是对的,它比我的要好得多。
    • @KarlKieninger 很高兴帮助传递知识。如果您确实需要将Total 放在状态列中并且没有能力使用中间应用程序层添加此值以进行显示,但不一定关心查询时间(可能来自直接来自例如 SQL 报告机制),您的方法可能是首选。
    • @MikeBrant:最好将你的用作子查询并替换空状态然后进行联合。优化器可能会处理得更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多