【问题标题】:Add a row with totals for each column为每列添加一行总计
【发布时间】:2012-11-30 18:39:35
【问题描述】:

我正在尝试向 SQL 选择查询添加一行,该查询包含一个总和(或任何其他操作,例如平均值)作为最后一行。在这方面,它类似于 GROUP BY ... WITH ROLLUP。

首先:假设我有一个表 t,其中包含字段 ID、A、B 和 C,所有这些都是数字。此外,ID 不是唯一的,而是一个类别。我的 SELECT 查询应该计算这些数字中有多少落在指定范围内。

因此,例如,最终结果将是

(SELECT t.ID, a.ac, b.bc, c.cc FROM t
LEFT JOIN (SELECT COUNT(*) cc,ID FROM t WHERE A BETWEEN 2 AND 4 GROUP BY ID) AS a ON a.ID=t.ID 
LEFT JOIN (SELECT AVG(B) cc,ID FROM t WHERE B BETWEEN 19 AND 40 GROUP BY ID) AS b ON b.ID=t.ID 
LEFT JOIN (SELECT COUNT(*) cc,ID FROM t WHERE C BETWEEN 12 AND 14 GROUP BY ID) AS c ON a.ID=t.ID GROUP BY t.ID) 

union 

(select 'Overall',
 (SELECT COUNT(*) cc FROM t WHERE A BETWEEN 2 AND 4),
 (SELECT AVG(B) cc FROM t WHERE B BETWEEN 19 AND 40),
 (SELECT COUNT(*) cc FROM t WHERE C BETWEEN 12 AND 14) );

但是,这个解决方案并不理想,因为我需要重新说明 A、B 和 C 的条件。我想知道是否有一种简单的方法可以只指定一次条件来完成相同的结果。

提前致谢。

【问题讨论】:

    标签: mysql sql union rollup


    【解决方案1】:

    我认为没有更简单的解决方案。但我会像这样重写你的查询:

    SELECT
      t.ID,
      count(case when A between 2 and 4 then ID end),
      AVG(case when B between 19 and 40 then B end),
      COUNT(case when C between 12 and 14 then id end)
    FROM t
    GROUP BY ID
    UNION
    select
      'Overall',
      count(case when A between 2 and 4 then ID end),
      AVG(case when B between 19 and 40 then B end),
      COUNT(case when C between 12 and 14 then id end)
    FROM t
    

    【讨论】:

    • +1,你可以在第二个整体查询中做同样的事情,如果你想使用它,here is a demo
    • @MahmoudGamal 谢谢 :) 我在看到您的评论之前进行了编辑,与您的演示不同 :)
    【解决方案2】:

    好吧,没有平均数你可以做到:

    SELECT t.ID,
           count(case when A between 2 and 4 then ID end),
           AVG(case when B between 19 and 40 then B end),
           COUNT(case when C between 12 and 14 then id end)
    FROM t
    GROUP BY ID with rollup
    

    我会这样写:

    SELECT t.ID,
           sum(case when A between 2 and 4 then 1 else 0 end),
           sum(case when B between 19 and 40 then B end)/sum((case when B between 19 and 40 then B end),
           sum(case when C between 12 and 14 then 1 else end)
    FROM t
    GROUP BY ID with rollup
    

    我不确定 rollup 如何与 avg 一起工作,所以最终版本是:

    select coalesce(t.ID, 'Overall'), Acnt,
           (case when Bcnt > 0 then Bsum/Bcnt end),
           Ccnt
    from (select t.ID,
                 sum(case when A between 2 and 4 then 1 else 0 end) as Acnt,
                 sum(case when B between 19 and 40 then B end) as Bsum,
                 sum(case when B between 19 and 40 then B end) as Bcnt,
                 sum(case when C between 12 and 14 then 1 else end) as Ccnt
          FROM t
          GROUP BY ID with rollup
         ) t
    

    【讨论】:

      猜你喜欢
      • 2019-10-07
      • 1970-01-01
      • 2012-05-21
      • 1970-01-01
      • 1970-01-01
      • 2020-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多