Oracle中group by 后面的ROLLUP有什么用。

解决方案 »

  1.   

    ROLLUP:为每个分组返回小计记录。
    可以参考下面的例子。
      

  2.   

    你可以看一下,除了ROLLUP,还有CUBE.
      

  3.   

    --这是sql server中的解释,在oracle中几乎一样.
    用 ROLLUP 汇总数据
    在生成包含小计和合计的报表时,ROLLUP 运算符很有用。ROLLUP 运算符生成的结果集类似于 CUBE 运算符所生成的结果集。有关更多信息,请参见用 CUBE 汇总数据。 CUBE 和 ROLLUP 之间的区别在于: CUBE 生成的结果集显示了所选列中值的所有组合的聚合。
    ROLLUP 生成的结果集显示了所选列中值的某一层次结构的聚合。 
    例如,简单表 Inventory 中包含:Item                 Color                Quantity                   
    -------------------- -------------------- -------------------------- 
    Table                Blue                 124                        
    Table                Red                  223                        
    Chair                Blue                 101                        
    Chair                Red                  210                        下列查询将生成小计报表:SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'
                ELSE ISNULL(Item, 'UNKNOWN')
           END AS Item,
           CASE WHEN (GROUPING(Color) = 1) THEN 'ALL'
                ELSE ISNULL(Color, 'UNKNOWN')
           END AS Color,
           SUM(Quantity) AS QtySum
    FROM Inventory
    GROUP BY Item, Color WITH ROLLUPItem                 Color                QtySum                     
    -------------------- -------------------- -------------------------- 
    Chair                Blue                 101.00                     
    Chair                Red                  210.00                     
    Chair                ALL                  311.00                     
    Table                Blue                 124.00                     
    Table                Red                  223.00                     
    Table                ALL                  347.00                     
    ALL                  ALL                  658.00                     (7 row(s) affected)如果查询中的 ROLLUP 关键字更改为 CUBE,那么 CUBE 结果集与上述结果相同,只是在结果集的末尾还会返回下列两行:ALL                  Blue                 225.00                     
    ALL                  Red                  433.00                     CUBE 操作为 Item 和 Color 中值的可能组合生成行。例如,CUBE 不仅报告与 Item 值 Chair 相组合的 Color 值的所有可能组合(Red、Blue 和 Red + Blue),而且报告与 Color 值 Red 相组合的 Item 值的所有可能组合(Chair、Table 和 Chair + Table)。对于 GROUP BY 子句中右边的列中的每个值,ROLLUP 操作并不报告左边一列(或左边各列)中值的所有可能组合。例如,ROLLUP 并不对每个 Color 值报告 Item 值的所有可能组合。ROLLUP 操作的结果集具有类似于 COMPUTE BY 所返回结果集的功能;然而,ROLLUP 具有下列优点: ROLLUP 返回单个结果集;COMPUTE BY 返回多个结果集,而多个结果集会增加应用程序代码的复杂性。
    ROLLUP 可以在服务器游标中使用;COMPUTE BY 不可以。
    有时,查询优化器为 ROLLUP 生成的执行计划比为 COMPUTE BY 生成的更为高效。 
      

  4.   

    --oracle的几个用法.1.  Rollup: give the sum on the aggregate; it is used as an add-on to the GROUP BY clause   
    SQL> -- create demo table
    SQL> create table Employee(
      2    ID                 VARCHAR2(4 BYTE)         NOT NULL,
      3    First_Name         VARCHAR2(10 BYTE),
      4    Last_Name          VARCHAR2(10 BYTE),
      5    Start_Date         DATE,
      6    End_Date           DATE,
      7    Salary             Number(8,2),
      8    City               VARCHAR2(10 BYTE),
      9    Description        VARCHAR2(15 BYTE)
     10  )
     11  /Table created.SQL>
    SQL> -- prepare data
    SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
      2               values ('01','Jason',    'Martin',  to_date('19960725','YYYYMMDD'), to_date('20060725','YYYYMMDD'), 1234.56, 'Toronto',  'Programmer')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
      2                values('02','Alison',   'Mathews', to_date('19760321','YYYYMMDD'), to_date('19860221','YYYYMMDD'), 6661.78, 'Vancouver','Tester')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
      2                values('03','James',    'Smith',   to_date('19781212','YYYYMMDD'), to_date('19900315','YYYYMMDD'), 6544.78, 'Vancouver','Tester')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
      2                values('04','Celia',    'Rice',    to_date('19821024','YYYYMMDD'), to_date('19990421','YYYYMMDD'), 2344.78, 'Vancouver','Manager')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
      2                values('05','Robert',   'Black',   to_date('19840115','YYYYMMDD'), to_date('19980808','YYYYMMDD'), 2334.78, 'Vancouver','Tester')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
      2                values('06','Linda',    'Green',   to_date('19870730','YYYYMMDD'), to_date('19960104','YYYYMMDD'), 4322.78,'New York',  'Tester')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
      2                values('07','David',    'Larry',   to_date('19901231','YYYYMMDD'), to_date('19980212','YYYYMMDD'), 7897.78,'New York',  'Manager')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
      2                values('08','James',    'Cat',     to_date('19960917','YYYYMMDD'), to_date('20020415','YYYYMMDD'), 1232.78,'Vancouver', 'Tester')
      3  /1 row created.SQL>
    SQL>
    SQL>
    SQL> -- display data in the table
    SQL> select * from Employee
      2  /ID   FIRST_NAME LAST_NAME  START_DAT END_DATE      SALARY CITY       DESCRIPTION
    ---- ---------- ---------- --------- --------- ---------- ---------- ---------------
    01   Jason      Martin     25-JUL-96 25-JUL-06    1234.56 Toronto    Programmer
    02   Alison     Mathews    21-MAR-76 21-FEB-86    6661.78 Vancouver  Tester
    03   James      Smith      12-DEC-78 15-MAR-90    6544.78 Vancouver  Tester
    04   Celia      Rice       24-OCT-82 21-APR-99    2344.78 Vancouver  Manager
    05   Robert     Black      15-JAN-84 08-AUG-98    2334.78 Vancouver  Tester
    06   Linda      Green      30-JUL-87 04-JAN-96    4322.78 New York   Tester
    07   David      Larry      31-DEC-90 12-FEB-98    7897.78 New York   Manager
    08   James      Cat        17-SEP-96 15-APR-02    1232.78 Vancouver  Tester8 rows selected.SQL>
    SQL>
    SQL>
    SQL> -- Rollup: give the sum on the aggregate; it is used as an add-on to the GROUP BY clause.
    SQL>
    SQL> SELECT count(*), city
      2  FROM employee
      3  GROUP BY ROLLUP(city);  COUNT(*) CITY
    ---------- ----------
             2 New York
             1 Toronto
             5 Vancouver
             8SQL>
    SQL>
    SQL>
    SQL> -- clean the table
    SQL> drop table Employee
      2  /Table dropped.2.  With ROLLUP and ROW_NUMBER added   
    SQL> -- create demo table
    SQL> create table Employee(
      2    ID                 VARCHAR2(4 BYTE)         NOT NULL,
      3    First_Name         VARCHAR2(10 BYTE),
      4    Last_Name          VARCHAR2(10 BYTE),
      5    Start_Date         DATE,
      6    End_Date           DATE,
      7    Salary             Number(8,2),
      8    City               VARCHAR2(10 BYTE),
      9    Description        VARCHAR2(15 BYTE)
     10  )
     11  /Table created.SQL>
    SQL> -- prepare data
    SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
      2               values ('01','Jason',    'Martin',  to_date('19960725','YYYYMMDD'), to_date('20060725','YYYYMMDD'), 1234.56, 'Toronto',  'Programmer')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
      2                values('02','Alison',   'Mathews', to_date('19760321','YYYYMMDD'), to_date('19860221','YYYYMMDD'), 6661.78, 'Vancouver','Tester')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
      2                values('03','James',    'Smith',   to_date('19781212','YYYYMMDD'), to_date('19900315','YYYYMMDD'), 6544.78, 'Vancouver','Tester')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
      2                values('04','Celia',    'Rice',    to_date('19821024','YYYYMMDD'), to_date('19990421','YYYYMMDD'), 2344.78, 'Vancouver','Manager')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
      2                values('05','Robert',   'Black',   to_date('19840115','YYYYMMDD'), to_date('19980808','YYYYMMDD'), 2334.78, 'Vancouver','Tester')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
      2                values('06','Linda',    'Green',   to_date('19870730','YYYYMMDD'), to_date('19960104','YYYYMMDD'), 4322.78,'New York',  'Tester')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
      2                values('07','David',    'Larry',   to_date('19901231','YYYYMMDD'), to_date('19980212','YYYYMMDD'), 7897.78,'New York',  'Manager')
      3  /1 row created.SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
      2                values('08','James',    'Cat',     to_date('19960917','YYYYMMDD'), to_date('20020415','YYYYMMDD'), 1232.78,'Vancouver', 'Tester')
      3  /1 row created.SQL>
    SQL>
    SQL>
    SQL> -- display data in the table
    SQL> select * from Employee
      2  /ID   FIRST_NAME LAST_NAME  START_DAT END_DATE      SALARY CITY       DESCRIPTION
    ---- ---------- ---------- --------- --------- ---------- ---------- ---------------
    01   Jason      Martin     25-JUL-96 25-JUL-06    1234.56 Toronto    Programmer
    02   Alison     Mathews    21-MAR-76 21-FEB-86    6661.78 Vancouver  Tester
    03   James      Smith      12-DEC-78 15-MAR-90    6544.78 Vancouver  Tester
    04   Celia      Rice       24-OCT-82 21-APR-99    2344.78 Vancouver  Manager
    05   Robert     Black      15-JAN-84 08-AUG-98    2334.78 Vancouver  Tester
    06   Linda      Green      30-JUL-87 04-JAN-96    4322.78 New York   Tester
    07   David      Larry      31-DEC-90 12-FEB-98    7897.78 New York   Manager
    08   James      Cat        17-SEP-96 15-APR-02    1232.78 Vancouver  Tester8 rows selected.SQL>
    SQL>
    SQL>
    SQL> -- 
    SQL>
    SQL> SELECT ROW_NUMBER() OVER(ORDER BY city, description) rn,
      2    count(*), city, description
      3  FROM employee
      4  GROUP BY ROLLUP(city, description);        RN   COUNT(*) CITY       DESCRIPTION
    ---------- ---------- ---------- ---------------
             1          1 New York   Manager
             2          1 New York   Tester
             3          2 New York
             4          1 Toronto    Programmer
             5          1 Toronto
             6          1 Vancouver  Manager
             7          4 Vancouver  Tester
             8          5 Vancouver
             9          89 rows selected.SQL>
    SQL>
    SQL> -- clean the table
    SQL> drop table Employee
      2  /Table dropped.
     
      

  5.   

    3.  The ROLLUP clause extends GROUP BY to return a row containing a subtotal for each group along with a total for all groups   
    SQL> --Passing a Single Column to ROLLUP
    SQL> --The ROLLUP clause extends GROUP BY to return a row containing a subtotal for each group along with a total for all groups.
    SQL> SELECT city, SUM(salary)
      2  FROM employee
      3  GROUP BY city;CITY       SUM(SALARY)
    ---------- -----------
    New York      12220.56
    Toronto        1234.56
    Vancouver      19118.9SQL> --The following query rewrites the previous example to use ROLLUP.
    SQL> SELECT city, SUM(salary)
      2  FROM employee
      3  GROUP BY ROLLUP(city);CITY       SUM(SALARY)
    ---------- -----------
    New York      12220.56
    Toronto        1234.56
    Vancouver      19118.9
                  32574.024.  Changing the Position of Columns Passed to ROLLUP   
    SQL> -- Changing the Position of Columns Passed to ROLLUP
    SQL> SELECT city, description, SUM(salary)
      2  FROM employee
      3  GROUP BY ROLLUP(city, description);CITY       DESCRIPTION     SUM(SALARY)
    ---------- --------------- -----------
    Toronto    Programmer          1234.56
    Toronto                        1234.56
    New York   Tester              4322.78
    New York   Manager             7897.78
    New York                      12220.56
    Vancouver  Tester             16774.12
    Vancouver  Manager             2344.78
    Vancouver                      19118.9
                                  32574.029 rows selected.SQL> SELECT city, description, SUM(salary)
      2  FROM employee
      3  GROUP BY ROLLUP(description, city);CITY       DESCRIPTION     SUM(SALARY)
    ---------- --------------- -----------
    New York   Tester              4322.78
    Vancouver  Tester             16774.12
               Tester              21096.9
    New York   Manager             7897.78
    Vancouver  Manager             2344.78
               Manager            10242.56
    Toronto    Programmer          1234.56
               Programmer          1234.56
                                  32574.029 rows selected.5.  Passing Multiple Columns to ROLLUP: groups the rows into blocks with the same column values   
    SQL> -- Passing Multiple Columns to ROLLUP: groups the rows into blocks with the same column values.
    SQL> SELECT city, description, SUM(salary)
      2  FROM employee
      3  GROUP BY ROLLUP(city, description);CITY       DESCRIPTION     SUM(SALARY)
    ---------- --------------- -----------
    Toronto    Programmer          1234.56
    Toronto                        1234.56
    New York   Tester              4322.78
    New York   Manager             7897.78
    New York                      12220.56
    Vancouver  Tester             16774.12
    Vancouver  Manager             2344.78
    Vancouver                      19118.9
                                  32574.029 rows selected.6.  Using AVG with ROLLUP   
    SQL> --Using AVG with ROLLUP
    SQL> SELECT city, description, AVG(salary)
      2  FROM employee
      3  GROUP BY ROLLUP(city, description);CITY       DESCRIPTION     AVG(SALARY)
    ---------- --------------- -----------
    Toronto    Programmer          1234.56
    Toronto                        1234.56
    New York   Tester              4322.78
    New York   Manager             7897.78
    New York                       6110.28
    Vancouver  Tester              4193.53
    Vancouver  Manager             2344.78
    Vancouver                      3823.78
                                 4071.75259 rows selected.7.  Rollup function in group by clause   
    SQL> SELECT city, SUM(salary)
      2  FROM employee
      3  GROUP BY ROLLUP(city);CITY       SUM(SALARY)
    ---------- -----------
    New York      12220.56
    Toronto        1234.56
    Vancouver      19118.9
                  32574.028.  ROLLUP and RANK() to get the sales rankings by product type ID 
    SQL> CREATE TABLE all_sales (
      2    year INTEGER,
      3    month INTEGER,
      4    prd_type_id INTEGER,
      5    emp_id INTEGER ,
      6    amount NUMBER(8, 2)
      7  );Table created.SQL>
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,1    ,1          ,21    ,16034.84);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,2    ,1          ,21    ,15644.65);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,3    ,2          ,21    ,20167.83);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,4    ,2          ,21    ,25056.45);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,5    ,2          ,21    ,NULL);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,6    ,1          ,21    ,15564.66);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,7    ,1          ,21    ,15644.65);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,8    ,1          ,21    ,16434.82);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,9    ,1          ,21    ,19654.57);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,10   ,1          ,21    ,21764.19);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,11   ,1          ,21    ,13026.73);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2006,12   ,2          ,21    ,10034.64);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,1    ,2          ,22    ,16634.84);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,1    ,2          ,21    ,26034.84);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,2    ,1          ,21    ,12644.65);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,3    ,1          ,21    ,NULL);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,4    ,1          ,21    ,25026.45);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,5    ,1          ,21    ,17212.66);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,6    ,1          ,21    ,15564.26);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,7    ,2          ,21    ,62654.82);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,8    ,2          ,21    ,26434.82);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,9    ,2          ,21    ,15644.65);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,10   ,2          ,21    ,21264.19);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,11   ,1          ,21    ,13026.73);
    SQL> insert into all_sales (YEAR,MONTH,PRD_TYPE_ID,EMP_ID,AMOUNT) values(2005,12   ,1          ,21    ,10032.64);
    SQL> select * from all_sales;
          YEAR      MONTH PRD_TYPE_ID     EMP_ID     AMOUNT
    ---------- ---------- ----------- ---------- ----------
          2006          1           1         21   16034.84
          2006          2           1         21   15644.65
          2006          3           2         21   20167.83
          2006          4           2         21   25056.45
          2006          5           2         21
          2006          6           1         21   15564.66
          2006          7           1         21   15644.65
          2006          8           1         21   16434.82
          2006          9           1         21   19654.57
          2006         10           1         21   21764.19
          2006         11           1         21   13026.73
          2006         12           2         21   10034.64
          2005          1           2         22   16634.84
          2005          1           2         21   26034.84
          2005          2           1         21   12644.65
          2005          3           1         21
          2005          4           1         21   25026.45
          2005          5           1         21   17212.66
          2005          6           1         21   15564.26
          2005          7           2         21   62654.82
          2005          8           2         21   26434.82
          2005          9           2         21   15644.65
          2005         10           2         21   21264.19
          2005         11           1         21   13026.73
          2005         12           1         21   10032.6425 rows selected.SQL>
    SQL> --ROLLUP and RANK() to get the sales rankings by product type ID
    SQL>
    SQL> SELECT
      2   prd_type_id, SUM(amount),
      3   RANK() OVER (ORDER BY SUM(amount) DESC) AS rank
      4  FROM all_sales
      5  GROUP BY ROLLUP(prd_type_id)
      6  ORDER BY prd_type_id;PRD_TYPE_ID SUM(AMOUNT)       RANK
    ----------- ----------- ----------
              1    227276.5          2
              2   223927.08          3
                  451203.58          1SQL>
    SQL> drop table all_sales;Table dropped.