Filtering groups with HAVING
Keep only the groups whose total passes a test.
HAVING filters the groups after GROUP BY, the way WHERE filters rows.
Show the authors with more than one book on the shelf, and how many they have, in a column called books.
| book_id | title | author | genre | year | pages |
|---|---|---|---|---|---|
| 1 | Emma | Jane Austen | Romance | 1815 | 474 |
| 2 | Pride and Prejudice | Jane Austen | Romance | 1813 | 432 |
| 3 | Charlie and the Chocolate Factory | Roald Dahl | Children | 1964 | 155 |
| 4 | A Study in Scarlet | Arthur Conan Doyle | Mystery | 1887 | 108 |
| 5 | Matilda | Roald Dahl | Children | 1988 | 240 |
| 6 | Dracula | Bram Stoker | Horror | 1897 | 418 |
| 7 | The Hunger Games | Suzanne Collins | Science Fiction | 2008 | 374 |
| 8 | Catching Fire | Suzanne Collins | Science Fiction | 2009 | 391 |
| 9 | Frankenstein | Mary Shelley | Horror | 1818 | 280 |
| 10 | The Da Vinci Code | Dan Brown | Thriller | 2003 | 454 |
Run your query to see the result table.
Press the green Run button or Ctrl+Enter.
How HAVING works
Rows into piles, piles into rows
books
| title | genre |
|---|---|
| Dune | Science Fiction |
| Dracula | Horror |
| Emma | Romance |
| 1984 | Science Fiction |
| Carrie | Horror |
| Mockingjay | Science Fiction |
| Pride and Prejudice | Romance |
| Frankenstein | Horror |
piles (GROUP BY genre)
result
| genre | books |
|---|---|
| Science Fiction | 3 |
| Horror | 3 |
SELECT genre, COUNT(*) AS books FROM books GROUP BY genre HAVING COUNT(*) >= 3;
HAVING tests each pile after counting: Romance has only 2, so it goes.
YOU WRITE
- SELECT
- FROM
- WHERE
- GROUP BY
- HAVING
- ORDER BY
- LIMIT
SQL WORKS THROUGH IT
- 1. FROM take the table
- 2. WHERE keep some rows
- 3. GROUP BY make piles
- 4. HAVING keep some piles
- 5. SELECT pick and work out columns
- 6. ORDER BY sort
- 7. LIMIT keep the first few
WHERE runs before the piles exist, so it can't see COUNT(*). HAVING runs after.
What does
HAVINGdo?GROUP BY genre HAVING COUNT(*) >= 3It keeps only the groups whose total passes a test. It's
WHEREfor groups.What's the difference between
WHEREandHAVING?WHEREpicks rows before they're grouped, so it can't useCOUNTorSUM.HAVINGpicks groups after they're counted. A query can have both.What order do the parts go in?
SELECT...FROM...WHERE...GROUP BY...HAVING...ORDER BY...LIMIT.Can
HAVINGuse a different total?Yes: with
HAVING SUM(pages) > 1000, the query can still showCOUNT(*), but keeps only genres with over 1,000 pages.How is this like Excel?
Like filtering a PivotTable by its values ("Value Filters"), or
FILTERon aCOUNTIFcolumn:=FILTER(A2:B9, B2:B9>=3).
How other databases do it
The lessons run on SQLite. Most of SQL is the same everywhere; these are the places where this lesson's SQL differs.
| Database | How | Note |
|---|---|---|
| SQLite (these lessons) | Works | But repeating COUNT(*) works everywhere. |
| PostgreSQL | Error | Repeat the function: HAVING COUNT(*) >= 3. |
| MySQL / MariaDB | Works | |
| SQL Server | Error | Repeat the function: HAVING COUNT(*) >= 3. |
| Oracle | Works from 23ai | Older versions give ORA-00904: repeat the function, HAVING COUNT(*) >= 3. |
| Sybase ASE | Error | Repeat the function: HAVING COUNT(*) >= 3. |
Know someone fighting with a spreadsheet? Send them this page.