NULL, the missing value
NULL means "unknown", not zero or empty. Why = NULL never matches, how IS NULL and COALESCE work, and what NULL does to COUNT and AVG.
NULL means unknown
NULL is not 0 and not an empty string. It means "no value here, we do not know". A game nobody has reviewed yet has a critic_score of NULL; a session that was quit early has no score.
Because NULL is unknown, any comparison with it is unknown too. Is an unknown score bigger than 50? Unknown. Is it equal to NULL? Also unknown. WHERE only keeps rows where the test is true, so WHERE score = NULL keeps nothing, ever. The same goes for != NULL.
To ask about NULL, use the special tests IS NULL and IS NOT NULL.
NULL in maths and totals
- Maths with NULL gives NULL:
NULL + 10is NULL. - Aggregates skip NULLs.
COUNT(*)counts rows,COUNT(score)counts rows that have a score, andAVG(score)is the average of the scores that exist. COALESCE(a, b)gives back the first value that is not NULL.COALESCE(score, 0)turns a missing score into 0 for display.
Run it: games without a critic score
Run it, then change one thing and run it again.
Tables games, players, sessions
| id | title | genre | year | price | multiplayer | critic_score |
|---|---|---|---|---|---|---|
| 1 | Pocket Kingdom | strategy | 2021 | 14.99 | 0 | 86 |
| 2 | Neon Drift | racing | 2023 | 19.99 | 1 | 93 |
| 3 | Hollow Pines | horror | 2020 | 9.99 | 0 | 87 |
| 4 | Star Courier | adventure | 2022 | 24.99 | 0 | 86 |
| 5 | Block Party | party | 2019 | 4.99 | 1 | 90 |
| 6 | Tiny Tactics | strategy | 2024 | 12.99 | 1 | 95 |
| 7 | Moonlit Farm | simulation | 2021 | 13.99 | 1 | 70 |
| 8 | Skyline Rush | platformer | 2018 | 7.99 | 0 | 69 |
| 9 | Deep Signal | horror | 2024 | 17.99 | 0 | 90 |
| 10 | Goal Machine | sports | 2025 | 29.99 | 1 | 88 |
| 11 | Paper Knights | rpg | 2022 | 19.99 | 0 | 69 |
| 12 | Cloud Cafe | simulation | 2023 | 11.99 | 0 | 64 |
First 12 of 30 rows. Query the table to see the rest.
| id | gamertag | country | joined_on |
|---|---|---|---|
| 1 | NoScopeNan | UK | 2024-01-31 |
| 2 | xX_Toast_Xx | Canada | 2025-04-20 |
| 3 | LagIsMyFault | Australia | 2024-11-30 |
| 4 | QuietKeyboard | Ireland | 2025-03-27 |
| 5 | BrbSnacks | USA | 2024-07-19 |
| 6 | MumSaysBedtime | UK | 2025-06-15 |
| 7 | ZeroDeaths | Sweden | 2024-08-27 |
| 8 | AFKAlex | USA | 2024-10-28 |
| 9 | PixelPriya | India | 2025-05-26 |
| 10 | CtrlAltDefeat | UK | 2024-01-05 |
| 11 | SirLagsALot | Germany | 2024-03-28 |
| 12 | MidnightMo | UK | 2025-04-13 |
First 12 of 24 rows. Query the table to see the rest.
| id | player_id | game_id | played_on | minutes | score |
|---|---|---|---|---|---|
| 1 | 21 | 10 | 2026-09-01 | 90 | 990 |
| 2 | 16 | 22 | 2026-09-01 | 90 | 1740 |
| 3 | 17 | 17 | 2026-09-01 | 40 | 1580 |
| 4 | 3 | 17 | 2026-09-01 | 30 | 2500 |
| 5 | 4 | 17 | 2026-09-01 | 90 | 1010 |
| 6 | 13 | 22 | 2026-09-01 | 20 | 1620 |
| 7 | 9 | 15 | 2026-09-01 | 90 | 140 |
| 8 | 12 | 30 | 2026-09-01 | 20 | 1120 |
| 9 | 2 | 16 | 2026-09-01 | 90 | 1280 |
| 10 | 8 | 2 | 2026-09-02 | 25 | 770 |
| 11 | 5 | 22 | 2026-09-02 | 15 | 1260 |
| 12 | 12 | 30 | 2026-09-02 | 25 | 2080 |
First 12 of 240 rows. Query the table to see the rest.
SELECT COUNT(*) AS sessions,
COUNT(score) AS with_score,
COUNT(*) - COUNT(score) AS no_score
FROM sessions;
SELECT title, critic_score, COALESCE(critic_score, 'not rated yet') AS shown
FROM games
WHERE critic_score IS NULL OR critic_score >= 93;
The unrated games list is empty
The store wants the title and genre of every game that has no critic score yet, to send them to reviewers. The query runs and returns nothing, but there are two. Fix it.
SELECT title, genre FROM games WHERE critic_score = NULL;