In SQL Server, the GROUPING()
function is used to distinguish the null values that are returned by ROLLUP
, CUBE
, or GROUPING SETS
from standard null values.
Basically it tells us whether a specified column expression in a GROUP BY
list is aggregated or not.
The GROUPING()
function returns either 1
or 0
(1
indicates that the column expression is aggregated and 0
indicates that it’s not).
Example
Suppose we have the following table:
SELECT * FROM Dogs;
Result:
DogName Activity Score ------- ----------- ----- Bruno Fetch Stick 43 Cooper Fetch Stick 43 Max Fetch Stick 91 Bruno Wag Tail 65 Cooper Wag Tail 51 Max Wag Tail 87 Bruno Keep Quiet 3 Cooper Keep Quiet null Max Keep Quiet 1
This is a table of dogs and their scores at performing various activities.
Here’s an example of using the GROUPING()
function against that data:
SELECT
Activity,
SUM(Score) AS "Score",
GROUPING(Activity) AS "Grouping"
FROM Dogs
GROUP BY ROLLUP (Activity);
Result:
Activity Score Grouping ----------- ----- -------- Fetch Stick 177 0 Keep Quiet 4 0 Wag Tail 203 0 null 384 1
Here I used the SUM()
aggregate function to calculate the total scores of each dog for each activity. I also used GROUP BY ROLLUP
to provide a grand total of all the scores.
And I used the GROUPING()
function to provide a column that indicates whether the specified column in the GROUP BY
list is aggregated or not. In other words, it tells us whether the null value in the Activity
column indicates that this is an aggregate.
The NULL
returned by ROLLUP
is a special use of NULL
. As Microsoft’s documentation states:
The
NULL
returned as the result of aROLLUP
,CUBE
orGROUPING SETS
operation is a special use ofNULL
. This acts as a column placeholder in the result set and means all.
So in our last row, the null value means “all”. And the TotalScore
column contains a sum of the preceding rows. And because of this, the Grouping
column contains 1
.
Changing the null Value
We can modify our code to replace NULL
with another value:
SELECT
IIF(GROUPING(Activity) = 1, 'Total', Activity) AS "Activity",
SUM(Score) AS "Score"
FROM Dogs
GROUP BY ROLLUP (Activity);
Result:
Activity Score ----------- ----- Fetch Stick 177 Keep Quiet 4 Wag Tail 203 Total 384
Here I passed GROUPING()
to the IIF()
function in order to evaluate whether or not GROUPING()
returned 1
or 0
. If 1
, then the null value is replaced with Total
. If 0
, then the column’s contents is returned as normal.
Doing this can help to eliminate any confusion over the meaning of the null value in the results.
Adding Another Column
Here’s an example that includes two columns in the ROLLUP
operation, as well as two instances of GROUPING()
in the SELECT
list:
SELECT
IIF(GROUPING(Activity) = 1, 'All Activities', Activity) AS "Activity",
IIF(GROUPING(DogName) = 1, 'All Dogs', DogName) AS "DogName",
SUM(Score) AS "Score"
FROM Dogs
GROUP BY ROLLUP (Activity, DogName);
Result:
Activity DogName Score -------------- -------- ----- Fetch Stick Bruno 43 Fetch Stick Cooper 43 Fetch Stick Max 91 Fetch Stick All Dogs 177 Keep Quiet Bruno 3 Keep Quiet Cooper null Keep Quiet Max 1 Keep Quiet All Dogs 4 Wag Tail Bruno 65 Wag Tail Cooper 51 Wag Tail Max 87 Wag Tail All Dogs 203 All Activities All Dogs 384
Here NULL
is replaced with a different message (either All Activities
or All Dogs
), depending on which column it concerns.