SQL: SELECT and WHERE

Play this lesson

An answer in 20 seconds

Kai asks: "How many gardens were defended yesterday in Europe?" Theo, the studio's data analyst, answers in 20 seconds by writing SQL, Structured Query Language, the language most databases and warehouses use for questions.

You won't need to type it here. You'll read it, which is most of the skill.

Theo's events table has one row per event and these columns:

SELECT, FROM, WHERE

The PostgreSQL docs split a query into three parts: the select list, the columns to return; the table list, after FROM; and an optional WHERE condition. Only rows where the condition is true come back.

SELECT player, level_id FROM events WHERE event_name = 'level_shared';

Text goes in single quotes, numbers don't. AND, OR and NOT combine conditions.

Pick the query

Which query lists the levels shared in Europe?

  1. SELECT level_id FROM events WHERE event_name = 'level_shared' AND region = 'eu'
  2. SELECT level_id FROM events WHERE event_name = 'level_shared' OR region = 'eu'
  3. SELECT level_id FROM events WHERE region = 'eu'
Show the answer

SELECT level_id FROM events WHERE event_name = 'level_shared' AND region = 'eu'

AND keeps rows where both are true. OR would also return every other event from Europe, and the last query has no event name at all.

Counting

Often the answer is a number, not a list. COUNT(*) counts the rows:

SELECT COUNT(*) FROM events WHERE event_name = 'garden_defended' AND region = 'eu' AND event_date = '2026-10-10';

One row comes back: 48,210. COUNT(level_id) would count only the rows where level_id isn't empty.

Sorting and the first few

ORDER BY sorts the result: smallest first by default, or largest first with DESC. LIMIT 10 returns at most 10 rows.

The PostgreSQL docs warn: without ORDER BY, rows come back in an unspecified order that must not be relied on. With LIMIT but no ORDER BY, you get an unpredictable set of rows.

Quick check

Without ORDER BY, a query always returns rows in the order they were added.

Show the answer

False

The order is unspecified and depends on how the database reads the data, so it can change between runs. Only ORDER BY guarantees an order.

The trap called NULL

A NULL is a missing value. Gardens defended on the studio's own maps have no level_id, so it is NULL.

The PostgreSQL docs explain: comparing anything with NULL gives NULL, meaning "unknown", not true or false. Even NULL = NULL is unknown. So WHERE level_id = NULL never matches a row.

Use IS NULL and IS NOT NULL instead.

Bug hunt

studio_maps.sql
SELECT COUNT(*)FROM eventsWHERE event_name =  'garden_defended'  AND level_id = NULL;

Theo wants gardens defended on the studio's own maps, which have no level_id. The answer is always 0. Which line is the bug?

  1. Line 5
  2. Line 1
  3. Line 3
Show the answer

Line 5

level_id = NULL is never true, because a comparison with NULL is unknown. Line 5 should say level_id IS NULL.

One number per day

One count answers one question. Kai wants a count for every day of the week, and Remy wants to link shares to the levels they came from.

Bolt says: Next: GROUP BY and JOIN.

Fact-checked 11 October 2026