Grouping Rows with GROUP BY

GROUPING

The GROUPING function tells us whether or not a null in a result set represents the set of all values produced by a GROUPING SETS, ROLLUP, or CUBE operation. A value of "1" tells us it does, a value of "0" tells us it does not. In the output of the following query two of the four nulls represent the set of all GRP_B values.

set null '(null)'

select
  grp_a
, grp_b
, count(*)
, GROUPING( GRP_A ) GROUPING_GRP_A
, GROUPING( GRP_B ) GROUPING_GRP_B
from
  t2
group by
  grouping sets( (grp_a, grp_b), grp_a )
order by
  1
, 2
;
 
GRP_A      GRP_B        COUNT(*) GROUPING_GRP_A GROUPING_GRP_B
---------- ---------- ---------- -------------- --------------
A1         X1                  1              0              0
A1         X2                  1              0              0
A1         (null)              3              0              0
A1         (null)              5              0              1
A2         (null)              1              0              0
A2         (null)              1              0              1
 

Of course adding a column with zeros and ones to a report isn't the most user friendly way to distinguish grouped values. However, GROUPING can be used with DECODE to insert labels like "Total" into the result set. Here is one example.

select
  grp_a as "Group A"
,
  decode
  ( GROUPING( GRP_B )
  , 1, 'Total:'
  , grp_b
  ) as "Group B"
,
  count(*) as "Count"
from
  t2
group by
  grouping sets( (grp_a, grp_b), grp_a )
order by
  grp_a
, GROUPING( GRP_B )
, grp_b
;
 
Group A    Group B         Count
---------- ---------- ----------
A1         X1                  1
A1         X2                  1
A1         (null)              3
A1         Total:              5
A2         (null)              1
A2         Total:              1
 

Nulls and Aggregate Functions

In this topic we explored working with null values in GROUP BY columns. To learn how aggregate functions like COUNT() and SUM() deal with null values in non-GROUP BY columns see Nulls and Aggregate Functions.

Gotcha - ORA-00979

When using ORDER BY we need to be careful with the selection of column aliases. For example, say we attempted this query.

select
  grp_a
, decode( grouping( grp_b ), 1, 'Total:', grp_b ) AS GRP_B
, count(*)
from t2
group by grouping sets( (grp_a, grp_b), grp_a )
order by grouping( GRP_B )
;
, decode( grouping( grp_b ), 1, 'Total:', grp_b ) AS GRP_B
  *
ERROR at line 3:
ORA-00979: not a GROUP BY expression


 

Note how the table has a column called GRP_B and the SELECT list has a column alias also called GRP_B. In the ORDER BY GROUPING( GRP_B ) clause one might expect the "GRP_B" term to refer to the table column, but Oracle interprets it as referring to the column alias, hence the ORA-00979 error.

To work around the error we can either prefix the column name with its table name

select
  grp_a
, decode( grouping( grp_b ), 1, 'Total:', grp_b ) AS GRP_B
, count(*)
from t2
group by grouping sets( (grp_a, grp_b), grp_a )
order by grouping( T2.GRP_B )
;
 
GRP_A      GRP_B        COUNT(*)
---------- ---------- ----------
A1         (null)              3
A1         X1                  1
A1         X2                  1
A2         (null)              1
A1         Total:              5
A2         Total:              1
 

or change the column alias.

select
  grp_a as "Group A"
, decode( grouping( grp_b ), 1, 'Total:', grp_b ) AS "Group B"
, count(*) as "Count"
from t2
group by grouping sets( (grp_a, grp_b), grp_a )
order by grouping( GRP_B )
;
 
Group A    Group B         Count
---------- ---------- ----------
A1         (null)              3
A1         X1                  1
A1         X2                  1
A2         (null)              1
A1         Total:              5
A2         Total:              1
 



Linking to SQL Snippets ™

To link to this page in Oracle Technology Network Forums or OraFAQ Forums cut and paste this code.

  • [url=http://www.sqlsnippets.com/en/topic-13138.html]SQL Snippets: Grouping Rows with GROUP BY - GROUPING[/url]

To link to this page in HTML documents or Blogger comments cut and paste this code.

  • <a href="http://www.sqlsnippets.com/en/topic-13138.html">SQL Snippets: Grouping Rows with GROUP BY - GROUPING</a>

To link to this page in other web sites use the following values.

  • Link Text : SQL Snippets: Grouping Rows with GROUP BY - GROUPING
  • URL (href): http://www.sqlsnippets.com/en/topic-13138.html