VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
GROUP BY gives you 1 row per group and no row for the whole. WITH ROLLUP
adds that row, and the subtotals in between when you group on several columns.
It saves running a second query and adding the numbers up yourself.
Open the client with mysql -u root -p sakila before you start.
How WITH ROLLUP works
GROUPING_COLUMN with the column that defines the groups, TABLE_NAME
with the table, and AGGREGATE_FUNCTION(COLUMN_NAME) with what to work out per
group. WITH ROLLUP goes at the end of the GROUP BY clause.
The server returns the normal groups, then extra rows where a grouping column
is set aside and its aggregate covers everything. It puts NULL in the columns
it set aside, which is how you spot those rows.
Examples
1) Add a total row
2) Subtotals as well
Group on 2 columns and you get a subtotal per value of the first, then the grand total.G / NULL / 3 is the subtotal for G
across every rate. NULL / NULL / 10 is the grand total, which matches the 10
films that run 185 minutes.
The rollup rows follow the groups they summarise rather than collecting at the
bottom, so the result reads top to bottom as a report.
Telling a rollup NULL from a real one
The NULL in a rollup row means “every value of this column”. A NULL in the data means “no value recorded”. They print identically, so on a column that can be NULL you cannot tell the 2 apart by looking.GROUPING() answers the question directly. It returns 1 when the column was
set aside for that row and 0 otherwise.
rating is never NULL in Sakila, so here the 2 questions have the same answer.
On a column that does hold NULLs, testing rating IS NULL would catch both
kinds of row and GROUPING(rating) = 1 catches only the rollup.
ORDER BY moves the total, and changes the sort
The examples above have noORDER BY, which is deliberate: WITH ROLLUP puts
each rollup row directly under the groups it summarises, and sorting throws that
arrangement away.
ENUM declared order that GROUP BY showed, because
sorting a rollup result sorts it as text.
So decide which you want. Leave ORDER BY off for a report that reads as
subtotals under their groups, or add it and accept that the rollup rows land
wherever the sort puts them.
Labelling the rollup rows
A column of NULLs is not what you want in a report.COALESCE returns its
first argument that is not NULL, so it puts a word there instead.
rating is never NULL in the
data. On a column that can be NULL, COALESCE would label real gaps as totals,
so use GROUPING() in the test instead.
Summary
- Add
WITH ROLLUPto the end ofGROUP BYto get subtotal and total rows. - Read NULL in a grouping column as “every value of this column”.
- Expect a subtotal per value of each earlier column when you group on several.
- Use
GROUPING(column)to tell a rollup row from a row where the data is NULL. - Expect
ORDER BYto move the rollup rows and to sort anENUMas text.
See also
- GROUP BY — the groups this adds totals to
- Aggregate functions — what gets totalled
- IS NULL — the other thing a NULL in that column can mean
- MySQL GROUP BY performance — what grouping costs at scale

