代码之家  ›  专栏  ›  技术社区  ›  sernaferna

使用GROUP BY进行Oracle SQL查询以汇总统计信息

  •  2
  • sernaferna  · 技术社区  · 17 年前

    ID   BATCH   STATUS
    1    1       0
    2    1       0
    3    1       1
    4    2       0
    

    是主键,每个“批次”都有多行,每行都有一个状态代码

    我需要写一个查询来总结

    BATCH  STATUS0  STATUS1  STATUS2
    1      2        1        0
    2      1        0        0
    

    • 状态

    • 状态
    • 状态

    SELECT batch, COUNT(status)
    FROM table
    WHERE status = 0
    GROUP BY batch
    

    状态 有一列

    4 回复  |  直到 17 年前
        1
  •  6
  •   Tony Andrews    17 年前
    select batch 
    ,      count(case when status=1 then 1 end) status1
    ,      count(case when status=2 then 1 end) status2
    ,      count(case when status=3 then 1 end) status3
    from   table
    group by batch;
    

    on my blog .

    使用DECODE的版本(特定于Oracle,但不太冗长):

    select batch 
    ,      count(decode(status,1,1)) status1
    ,      count(decode(status,2,1)) status2
    ,      count(decode(status,3,1)) status3
    from   table
    group by batch;
    
        2
  •  1
  •   tekBlues    17 年前
    select batch,
    sum(select case when status = 0 then 1 else 0 end) status0,
    sum(select case when status = 1 then 1 else 0 end) status1,
    sum(select case when status = 2 then 1 else 0 end) status2
    from table
    group by batch
    
        3
  •  1
  •   diederikh    17 年前
    select batch,
    sum((decode(status,0,1,0)) status0,
    sum((decode(status,1,1,0)) status1,
    sum((decode(status,2,1,0)) status2,
    from table
    group by batch
    
        4
  •  1
  •   Community Mohan Dere    9 年前

    OP询问一种方法(SUM)是否比另一种(COUNT)有任何性能优势。在一个有26K行的表上运行一个简单的测试表明,COUNT方法明显更快。YMMV。

    DECLARE
      CURSOR B IS
         select batch_id
           FROM batch
          WHERE ROWNUM < 2000;
    
      v_t1  NUMBER;
      v_t2  NUMBER;
      v_c1  NUMBER;
      v_c2  NUMBER;
      v_opn INTEGER;
      v_cls INTEGER;
      v_btc VARCHAR2(100);
    BEGIN
    -- Loop using SUM
      v_t1 := dbms_utility.get_time;
      v_c1 := dbms_utility.get_cpu_time;
      FOR R IN B LOOP
         FOR R2 IN (SELECT batch_type_code
                         , SUM(decode(batch_status_code, 'CLOSED', 1, 0)) closed
                         , SUM(decode(batch_status_code, 'OPEN', 1, 0)) OPEN
                         , SUM(decode(batch_status_code, 'REWORK', 1, 0)) rework
                      FROM batch
                     GROUP BY batch_type_code) LOOP 
            v_opn := R2.open;
            v_cls := R2.closed;
         END LOOP;
      END LOOP;
      v_t2 := dbms_utility.get_time;
      v_c2 := dbms_utility.get_cpu_time;
      dbms_output.put_line('For loop using SUM:');
      dbms_output.put_line('CPU seconds used: '||(v_c2 - v_c1)/100);
      dbms_output.put_line('Elapsed time: '||(v_t2 - v_t1)/100);
    
    -- Loop using COUNT
      v_t1 := dbms_utility.get_time;
      v_c1 := dbms_utility.get_cpu_time;
      FOR R IN B LOOP
         FOR R2 IN (SELECT batch_type_code
                         , COUNT(CASE WHEN batch_status_code = 'CLOSED' THEN 1 END) closed
                         , COUNT(CASE WHEN batch_status_code = 'OPEN' THEN 1 END) OPEN
                         , COUNT(CASE WHEN batch_status_code = 'REWORK' THEN 1 END) rework
                      FROM batch
                     GROUP BY batch_type_code) LOOP 
            v_opn := R2.open;
            v_cls := R2.closed;
         END LOOP;
      END LOOP;
      v_t2 := dbms_utility.get_time;
      v_c2 := dbms_utility.get_cpu_time;
      dbms_output.put_line('For loop using COUNT:');
      dbms_output.put_line('CPU seconds used: '||(v_c2 - v_c1)/100);
      dbms_output.put_line('Elapsed time: '||(v_t2 - v_t1)/100);
    END;
    /
    

    这产生了以下输出:

    For loop using SUM:
    CPU seconds used: 40
    Elapsed time: 40.09
    For loop using COUNT:
    CPU seconds used: 33.26
    Elapsed time: 33.34
    

    编辑:这是我用来回答的测试工具 a similar question