在分组集中收集计数

Gathering counts in grouping sets

我阅读了有关分组集的内容,我想收集组(A、B、C CNT 列)、(A,B)、(A) 的计数和总数

以下是我的测试案例和预期结果。我不确定如何生成 CNT 列作为输出的一部分。我怀疑它可能是一个计数(*),但我不确定如何将它与每个组结合起来。以下是我的预期结果

请注意虽然日期是完整的 'DD-MON-YYYY HH24:MI:SS' 因为我的 NLS_DATE_FORMAT 我只想在 'DD-MON-YYYY ' 部分分组并且不希望时间作为输出的一部分.让我的用户为 SESSION 输入另一个 NLS_DATE_FORMAT 将导致可预见的问题。

此外,我想在每个 'Total'

之后包含文本

我不喜欢分组集的想法,但它看起来最容易实现。我还偶然发现了 ROLLUP 命令,那会是更好的方法吗?

提前感谢您的时间、耐心和专业知识。

    My expected results 

     A       B C   CNT  
    20210805 1 1  2  
    20210805 1 2  1 
    20210805 2 1  2
    20210805 2 2  1
 Total AB         6 
   20210806  1 1  2  
   20210806  1 2  1 
   20210806  2 1  2
   20210806  2 2  1
 Total AB         6
 Total A         12
    
    ALTER SESSION SET 
       NLS_DATE_FORMAT = 'MMDDYYYY HH24:MI:SS';

    CREATE table abc(
          a DATE,
          b NUMBER(4),
          c NUMBER(4)
     );

    INSERT into abc (a,b,c) VALUES     
  (to_date('05-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 1,1);

    INSERT into abc (a,b,c) VALUES     
  (to_date('05-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 1,1);

  INSERT into abc (a,b,c) VALUES     
  (to_date('05-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 1,2);

  INSERT into abc (a,b,c) VALUES     
  (to_date('05-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 2,1);

  INSERT into abc (a,b,c) VALUES     
  (to_date('05-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 2,1);

  INSERT into abc (a,b,c) VALUES     
  (to_date('05-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 2,2);

  INSERT into abc (a,b,c) VALUES     
  (to_date('06-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 1,1);

  INSERT into abc (a,b,c) VALUES     
  (to_date('06-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 1,1);

  INSERT into abc (a,b,c) VALUES     
  (to_date('06-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 1,2);

  INSERT into abc (a,b,c) VALUES     
  (to_date('06-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 2,1);

  INSERT into abc (a,b,c) VALUES     
  (to_date('06-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 2,1);

  INSERT into abc (a,b,c) VALUES     
  (to_date('06-AUG-2021 10:00:00','DD-MON-YYYY HH24:MI:SS'), 2,2);

   SELECT
      TRUNC(a),b,c,  
grouping_id(a,b,c) the_grouping_id

   FROM abc
    group by grouping sets
    (
        (a,b,c),
        (a,b),
        (a)
    )
   order by a,b,c;

您正在分组的集合与您的示例输出不匹配。

您在每一天下都有小计,那只是集合 (A)

然后你有一个总的小计,那就是集合()

您确实需要一个 COUNT(*),它只是作为另一列添加到 SELECT 子句中。

您似乎不需要分组 ID。

并且您的 table 具有 A 作为 DATE 数据类型,因此值在插入时被 t运行 分类,不需要在 运行 时这样做。

所以...

SELECT
  A, B, C, COUNT(*)
FROM
  abc
GROUP BY
  GROUPING SETS (
    (A,B,C),
    (A),
    ()
  )
ORDER BY
  A, B, C

编辑: 根据评论,确实需要 TRUNC()

我会使用子查询或 CTE 只应用一次。

这给...

SELECT
  A, B, C, COUNT(*)
FROM
(
  SELECT TRUNC(A) A, B, C FROM abc
)
  abc_trunc
GROUP BY
  GROUPING SETS (
    (A,B,C),
    (A),
    ()
  )
ORDER BY
  A, B, C

生成行headers

   SELECT  a,b,c, count(*) n,
     case grouping_id(a,b,c) when 7 then 'Grand total'
                             when 3 then 'Total A' 
                             when 1 then 'Total AB' end row_header         
   FROM abc
   GROUP BY 
    GROUPING SETS (
        (a,b,c),
        (a,b),
        (a), 
        ()
    )
   ORDER BY a,b,c;

如果您需要截断实际列,请在查询中始终使用 TRUNC

   SELECT  trunc(a) x, b,c, count(*) n,
     case grouping_id(trunc(a),b,c) when 7 then 'Grand total'
                             when 3 then 'Total A' 
                             when 1 then 'Total AB' end row_header         
   FROM abc
   GROUP BY 
    GROUPING SETS (
        (trunc(a),b,c),
        (trunc(a),b),
        (trunc(a)), 
        ()
    )
   ORDER BY trunc(a),b,c;