Examples of grouping sets, cube, and rollup queries

The following examples illustrate the grouping, cube, and rollup forms of subselect queries.

The queries in Example 1 through Example 4 use a subset of the rows in the SALES tables based on the predicate 'WEEK(SALES_DATE) = 13'.

  SELECT WEEK(SALES_DATE) AS WEEK, 
         DAYOFWEEK(SALES_DATE) AS DAY_WEEK, 
         SALES_PERSON, SALES AS UNITS_SOLD 
  FROM SALES 
  WHERE WEEK(SALES_DATE) = 13

which results in:

  WEEK        DAY_WEEK    SALES_PERSON    UNITS_SOLD 
  ----------- ----------- --------------- -----------
           13           6 LUCCHESSI                 3
           13           6 LUCCHESSI                 1
           13           6 LEE                       2
           13           6 LEE                       2
           13           6 LEE                       3
           13           6 LEE                       5
           13           6 GOUNOT                    3
           13           6 GOUNOT                    1
           13           6 GOUNOT                    7
           13           7 LUCCHESSI                 1
           13           7 LUCCHESSI                 2
           13           7 LUCCHESSI                 1
           13           7 LEE                       7
           13           7 LEE                       3
           13           7 LEE                       7
           13           7 LEE                       4
           13           7 GOUNOT                    2
           13           7 GOUNOT                   18
           13           7 GOUNOT                    1
  • Example 1:  Here is a query with a basic GROUP BY clause over 3 columns:
      SELECT WEEK(SALES_DATE) AS WEEK,
             DAYOFWEEK(SALES_DATE) AS DAY_WEEK,
             SALES_PERSON, SUM(SALES) AS UNITS_SOLD       
      FROM SALES
      WHERE WEEK(SALES_DATE) = 13
      GROUP BY WEEK(SALES_DATE), DAYOFWEEK(SALES_DATE), SALES_PERSON
      ORDER BY WEEK, DAY_WEEK, SALES_PERSON

    This results in:

      WEEK        DAY_WEEK    SALES_PERSON    UNITS_SOLD 
      ----------- ----------- --------------- -----------
               13           6 GOUNOT                   11
               13           6 LEE                      12
               13           6 LUCCHESSI                 4
               13           7 GOUNOT                   21
               13           7 LEE                      21
               13           7 LUCCHESSI                 4
  • Example 2:  Produce the result based on two different grouping sets of rows from the SALES table.
      SELECT WEEK(SALES_DATE) AS WEEK,
             DAYOFWEEK(SALES_DATE) AS DAY_WEEK,
             SALES_PERSON, SUM(SALES) AS UNITS_SOLD       
      FROM SALES 
      WHERE WEEK(SALES_DATE) = 13
      GROUP BY GROUPING SETS ( (WEEK(SALES_DATE), SALES_PERSON),
                               (DAYOFWEEK(SALES_DATE), SALES_PERSON))
      ORDER BY WEEK, DAY_WEEK, SALES_PERSON

    This results in:

      WEEK        DAY_WEEK    SALES_PERSON    UNITS_SOLD 
      ----------- ----------- --------------- -----------
               13           - GOUNOT                   32
               13           - LEE                      33
               13           - LUCCHESSI                 8
                -           6 GOUNOT                   11
                -           6 LEE                      12
                -           6 LUCCHESSI                 4
                -           7 GOUNOT                   21
                -           7 LEE                      21
                -           7 LUCCHESSI                 4

    The rows with WEEK 13 are from the first grouping set and the other rows are from the second grouping set.

  • Example 3:  If you use the 3 distinct columns involved in the grouping sets of Example 2 and perform a ROLLUP, you can see grouping sets for (WEEK,DAY_WEEK,SALES_PERSON), (WEEK, DAY_WEEK), (WEEK) and grand total.
    SELECT WEEK(SALES_DATE) AS WEEK,
            DAYOFWEEK(SALES_DATE) AS DAY_WEEK,
            SALES_PERSON, SUM(SALES) AS UNITS_SOLD       
      FROM SALES
      WHERE WEEK(SALES_DATE) = 13
      GROUP BY ROLLUP ( WEEK(SALES_DATE), DAYOFWEEK(SALES_DATE), SALES_PERSON )
      ORDER BY WEEK, DAY_WEEK, SALES_PERSON

    This results in:

      WEEK        DAY_WEEK    SALES_PERSON    UNITS_SOLD 
      ----------- ----------- --------------- -----------
               13           6 GOUNOT                   11
               13           6 LEE                      12
               13           6 LUCCHESSI                 4
               13           6 -                        27
               13           7 GOUNOT                   21
               13           7 LEE                      21
               13           7 LUCCHESSI                 4
               13           7 -                        46
               13           - -                        73
                -           - -                        73
  • Example 4:  If you run the same query as Example 3 only replace ROLLUP with CUBE, you can see additional grouping sets for (WEEK,SALES_PERSON), (DAY_WEEK,SALES_PERSON), (DAY_WEEK), (SALES_PERSON) in the result.
      SELECT WEEK(SALES_DATE) AS WEEK,
             DAYOFWEEK(SALES_DATE) AS DAY_WEEK,
             SALES_PERSON, SUM(SALES) AS UNITS_SOLD       
      FROM SALES
      WHERE WEEK(SALES_DATE) = 13
      GROUP BY CUBE ( WEEK(SALES_DATE), DAYOFWEEK(SALES_DATE), SALES_PERSON )
      ORDER BY WEEK, DAY_WEEK, SALES_PERSON
    This results in:
      WEEK        DAY_WEEK    SALES_PERSON    UNITS_SOLD 
      ----------- ----------- --------------- -----------
               13           6 GOUNOT                   11
               13           6 LEE                      12
               13           6 LUCCHESSI                 4
               13           6 -                        27
               13           7 GOUNOT                   21
               13           7 LEE                      21
               13           7 LUCCHESSI                 4
               13           7 -                        46
               13           - GOUNOT                   32
               13           - LEE                      33
               13           - LUCCHESSI                 8
               13           - -                        73
                -           6 GOUNOT                   11
                -           6 LEE                      12
                -           6 LUCCHESSI                 4
                -           6 -                        27
                -           7 GOUNOT                   21
                -           7 LEE                      21
                -           7 LUCCHESSI                 4
                -           7 -                        46
                -           - GOUNOT                   32
                -           - LEE                      33
                -           - LUCCHESSI                 8
                -           - -                        73
  • Example 5:  Obtain a result set which includes a grand-total of selected rows from the SALES table together with a group of rows aggregated by SALES_PERSON and MONTH.
      SELECT SALES_PERSON,
             MONTH(SALES_DATE) AS MONTH,
             SUM(SALES) AS UNITS_SOLD
      FROM SALES
      GROUP BY GROUPING SETS ( (SALES_PERSON, MONTH(SALES_DATE)),
                               ()        
                             )
      ORDER BY SALES_PERSON, MONTH
    This results in:
      SALES_PERSON    MONTH       UNITS_SOLD 
      --------------- ----------- -----------
      GOUNOT                    3          35
      GOUNOT                    4          14
      GOUNOT                   12           1
      LEE                       3          60
      LEE                       4          25
      LEE                      12           6
      LUCCHESSI                 3           9
      LUCCHESSI                 4           4
      LUCCHESSI                12           1
      -                         -         155
  • Example 6:  This example shows two simple ROLLUP queries followed by a query which treats the two ROLLUPs as grouping sets in a single result set and specifies row ordering for each column involved in the grouping sets.
    • Example 6-1:
        SELECT WEEK(SALES_DATE) AS WEEK,
               DAYOFWEEK(SALES_DATE) AS DAY_WEEK,
               SUM(SALES) AS UNITS_SOLD
        FROM SALES
        GROUP BY ROLLUP ( WEEK(SALES_DATE), DAYOFWEEK(SALES_DATE) )
        ORDER BY WEEK, DAY_WEEK

      results in:

        WEEK        DAY_WEEK    UNITS_SOLD 
        ----------- ----------- -----------
                 13           6          27
                 13           7          46
                 13           -          73
                 14           1          31
                 14           2          43
                 14           -          74
                 53           1           8
                 53           -           8
                  -           -         155
    • Example 6-2:
        SELECT MONTH(SALES_DATE) AS MONTH,
               REGION,
               SUM(SALES) AS UNITS_SOLD
        FROM SALES
        GROUP BY ROLLUP ( MONTH(SALES_DATE), REGION );
        ORDER BY MONTH, REGION
      results in:
        MONTH       REGION          UNITS_SOLD 
        ----------- --------------- -----------
                  3 Manitoba                 22
                  3 Ontario-North             8
                  3 Ontario-South            34
                  3 Quebec                   40
                  3 -                       104
                  4 Manitoba                 17
                  4 Ontario-North             1
                  4 Ontario-South            14
                  4 Quebec                   11
                  4 -                        43
                 12 Manitoba                  2
                 12 Ontario-South             4
                 12 Quebec                    2
                 12 -                         8
                  - -                       155
    • Example 6-3:
        SELECT WEEK(SALES_DATE) AS WEEK,
               DAYOFWEEK(SALES_DATE) AS DAY_WEEK,
               MONTH(SALES_DATE) AS MONTH,
               REGION,
               SUM(SALES) AS UNITS_SOLD
        FROM SALES
        GROUP BY GROUPING SETS ( ROLLUP( WEEK(SALES_DATE), DAYOFWEEK(SALES_DATE) ),
                                 ROLLUP( MONTH(SALES_DATE), REGION )  )
      ORDER BY WEEK, DAY_WEEK, MONTH, REGION
      results in:
        WEEK        DAY_WEEK    MONTH       REGION          UNITS_SOLD 
        ----------- ----------- ----------- --------------- -----------
                 13           6           - -                        27
                 13           7           - -                        46
                 13           -           - -                        73
                 14           1           - -                        31
                 14           2           - -                        43
                 14           -           - -                        74
                 53           1           - -                         8
                 53           -           - -                         8
                  -           -           3 Manitoba                 22
                  -           -           3 Ontario-North             8
                  -           -           3 Ontario-South            34
                  -           -           3 Quebec                   40
                  -           -           3 -                       104
                  -           -           4 Manitoba                 17
                  -           -           4 Ontario-North             1
                  -           -           4 Ontario-South            14
                  -           -           4 Quebec                   11
                  -           -           4 -                        43
                  -           -          12 Manitoba                  2
                  -           -          12 Ontario-South             4
                  -           -          12 Quebec                    2
                  -           -          12 -                         8
                  -           -           - -                       155
                  -           -           - -                       155

      Using the two ROLLUPs as grouping sets causes the result to include duplicate rows. There are even two grand total rows.

      Observe how the use of ORDER BY has affected the results:
      • In the first grouped set, week 53 has been repositioned to the end.
      • In the second grouped set, month 12 has now been positioned to the end and the regions now display in alphabetic order.
      • Null values are sorted high.
  • Example 7:  In queries that perform multiple ROLLUPs in a single pass (such as Example 6-3) you might want to be able to indicate which grouping set produced each row. The following steps demonstrate how to provide a column (called GROUP) which indicates the origin of each row in the result set. Origin means which one of the two grouping sets produced the row in the result set.
    Step 1: Introduce a way of "generating" new data values, using a query which selects from a VALUES clause (which is an alternative form of a fullselect). This query shows how a table can be derived called "X" having 2 columns "R1" and "R2" and 1 row of data.
      SELECT R1,R2 
      FROM (VALUES('GROUP 1','GROUP 2')) AS X(R1,R2);
    results in:
      R1      R2     
      ------- -------
      GROUP 1 GROUP 2
    Step 2: Form the cross product of this table "X" with the SALES table. This add columns "R1" and "R2" to every row.
      SELECT R1, R2, WEEK(SALES_DATE) AS WEEK,
             DAYOFWEEK(SALES_DATE) AS DAY_WEEK,
             MONTH(SALES_DATE) AS MONTH,
             REGION,
             SALES AS UNITS_SOLD
      FROM SALES,(VALUES('GROUP 1','GROUP 2')) AS X(R1,R2)

    This add columns "R1" and "R2" to every row.

    Step 3: Now these columns can be combined with the grouping sets to include these columns in the rollup analysis.
      SELECT R1, R2, 
             WEEK(SALES_DATE) AS WEEK,
             DAYOFWEEK(SALES_DATE) AS DAY_WEEK,
             MONTH(SALES_DATE) AS MONTH,
             REGION, SUM(SALES) AS UNITS_SOLD
      FROM SALES,(VALUES('GROUP 1','GROUP 2')) AS X(R1,R2)
      GROUP BY GROUPING SETS ((R1, ROLLUP(WEEK(SALES_DATE),
                                DAYOFWEEK(SALES_DATE))),
                              (R2,ROLLUP( MONTH(SALES_DATE), REGION ) )  )
      ORDER BY WEEK, DAY_WEEK, MONTH, REGION
    results in:
      R1      R2      WEEK     DAY_WEEK  MONTH     REGION          UNITS_SOLD 
      ------- ------- -------- --------- --------- --------------- -----------
      GROUP 1 -             13         6         - -                        27
      GROUP 1 -             13         7         - -                        46
      GROUP 1 -             13         -         - -                        73
      GROUP 1 -             14         1         - -                        31
      GROUP 1 -             14         2         - -                        43
      GROUP 1 -             14         -         - -                        74
      GROUP 1 -             53         1         - -                         8
      GROUP 1 -             53         -         - -                         8
      -       GROUP 2        -         -         3 Manitoba                 22
      -       GROUP 2        -         -         3 Ontario-North             8
      -       GROUP 2        -         -         3 Ontario-South            34
      -       GROUP 2        -         -         3 Quebec                   40
      -       GROUP 2        -         -         3 -                       104
      -       GROUP 2        -         -         4 Manitoba                 17
      -       GROUP 2        -         -         4 Ontario-North             1
      -       GROUP 2        -         -         4 Ontario-South            14
      -       GROUP 2        -         -         4 Quebec                   11
      -       GROUP 2        -         -         4 -                        43
      -       GROUP 2        -         -        12 Manitoba                  2
      -       GROUP 2        -         -        12 Ontario-South             4
      -       GROUP 2        -         -        12 Quebec                    2
      -       GROUP 2        -         -        12 -                         8
      -       GROUP 2        -         -         - -                       155
      GROUP 1 -              -         -         - -                       155
    Step 4: Notice that because R1 and R2 are used in different grouping sets, whenever R1 is non-null in the result, R2 is null and whenever R2 is non-null in the result, R1 is null. That means you can consolidate these columns into a single column using the COALESCE function. You can also use this column in the ORDER BY clause to keep the results of the two grouping sets together.
      SELECT COALESCE(R1,R2) AS GROUP,
             WEEK(SALES_DATE) AS WEEK,
             DAYOFWEEK(SALES_DATE) AS DAY_WEEK,
             MONTH(SALES_DATE) AS MONTH,
             REGION, SUM(SALES) AS UNITS_SOLD
      FROM SALES,(VALUES('GROUP 1','GROUP 2')) AS X(R1,R2)
      GROUP BY GROUPING SETS ((R1, ROLLUP(WEEK(SALES_DATE),
                                DAYOFWEEK(SALES_DATE))),
                              (R2,ROLLUP( MONTH(SALES_DATE), REGION ) )  )
      ORDER BY GROUP, WEEK, DAY_WEEK, MONTH, REGION;
    results in:
      GROUP   WEEK        DAY_WEEK    MONTH       REGION          UNITS_SOLD 
      ------- ----------- ----------- ----------- --------------- -----------
      GROUP 1          13           6           - -                        27
      GROUP 1          13           7           - -                        46
      GROUP 1          13           -           - -                        73
      GROUP 1          14           1           - -                        31
      GROUP 1          14           2           - -                        43
      GROUP 1          14           -           - -                        74
      GROUP 1          53           1           - -                         8
      GROUP 1          53           -           - -                         8
      GROUP 1           -           -           - -                       155
      GROUP 2           -           -           3 Manitoba                 22
      GROUP 2           -           -           3 Ontario-North             8
      GROUP 2           -           -           3 Ontario-South            34
      GROUP 2           -           -           3 Quebec                   40
      GROUP 2           -           -           3 -                       104
      GROUP 2           -           -           4 Manitoba                 17
      GROUP 2           -           -           4 Ontario-North             1
      GROUP 2           -           -           4 Ontario-South            14
      GROUP 2           -           -           4 Quebec                   11
      GROUP 2           -           -           4 -                        43
      GROUP 2           -           -          12 Manitoba                  2
      GROUP 2           -           -          12 Ontario-South             4
      GROUP 2           -           -          12 Quebec                    2
      GROUP 2           -           -          12 -                         8
      GROUP 2           -           -           - -                       155
  • Example 8:  The following example illustrates the use of various aggregate functions when performing a CUBE. The example also makes use of cast functions and rounding to produce a decimal result with reasonable precision and scale.
      SELECT MONTH(SALES_DATE) AS MONTH,
             REGION,
             SUM(SALES) AS UNITS_SOLD, 
             MAX(SALES) AS BEST_SALE, 
             CAST(ROUND(AVG(DECIMAL(SALES)),2) AS DECIMAL(5,2)) AS AVG_UNITS_SOLD 
      FROM SALES 
      GROUP BY CUBE(MONTH(SALES_DATE),REGION)
      ORDER BY MONTH, REGION
    This results in:
    MONTH       REGION          UNITS_SOLD  BEST_SALE   AVG_UNITS_SOLD
    ----------- --------------- ----------- ----------- --------------
              3 Manitoba                 22           7           3.14
              3 Ontario-North             8           3           2.67
              3 Ontario-South            34          14           4.25
              3 Quebec                   40          18           5.00
              3 -                       104          18           4.00
              4 Manitoba                 17           9           5.67
              4 Ontario-North             1           1           1.00
              4 Ontario-South            14           8           4.67
              4 Quebec                   11           8           5.50
              4 -                        43           9           4.78
             12 Manitoba                  2           2           2.00
             12 Ontario-South             4           3           2.00
             12 Quebec                    2           1           1.00
             12 -                         8           3           1.60
              - Manitoba                 41           9           3.73
              - Ontario-North             9           3           2.25
              - Ontario-South            52          14           4.00
              - Quebec                   53          18           4.42
              - -                       155          18           3.87