RECAP

Window functions side by side

A window function works across rows but keeps every row, adding a new column. Pick a card to see it below on the same books and members.

ROW_NUMBER() OVER (ORDER BY year) numbers every row 1, 2, 3 in year order.

titleyearposition
Frankenstein18181
Dracula18972
Brave New World19323
Dune19654
Carrie19745
The Hunger Games20086

query

SELECT title, year, 
  ROW_NUMBER() OVER (ORDER BY year) AS position
FROM books;

Every row stays: GROUP BY would squash each genre into one row instead.

Compare

The three numbering functions on a tie

nameloansROW_NUMBERRANKDENSE_RANK
Ava3111
Ben2222
Cara2322
Dev1443

Ben and Cara tie on 2 loans. ROW_NUMBER still splits them (in no fixed order); RANK gives both 2 and skips 3; DENSE_RANK gives both 2 and carries on at 3.

Compare

GROUP BY or a window?

SUM(pages) ... GROUP BY genreSUM(pages) OVER (PARTITION BY genre)
Rows backOne per genreEvery book
Can show title?No: a group has many titlesYes, next to its genre's total
Filter on itHAVINGIn a WITH step, then WHERE
Good forSummariesRanks, running totals, "share of the total"
Good to know

Things people mix up

  • WHERE can't see a window column. WHERE runs before the window is worked out: number the rows in a WITH step, then filter on the number.
  • ORDER BY in OVER is not the result's order. It says how to count. Add a normal ORDER BY at the end to sort what comes back.
  • No ORDER BY in OVER means no running total. SUM(pages) OVER () puts the grand total on every row.
  • Ties in a running total. Rows that tie on the ORDER BY are added together. ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW adds them one at a time.
  • In Excel, RANK.EQ is RANK, a running total is =SUM($B$2:B2) filled down, and ROW_NUMBER per group is =COUNTIF($A$2:A2, A2).
  • Not every database has them. MySQL needs 8.0 or later, and Sybase ASE has none.
Practise

The lessons behind this page

Know someone fighting with a spreadsheet? Send them this page.