SQL basics: reading data
SELECT, WHERE, ORDER BY and LIMIT
The idea in 30 seconds
A query says which table to read, which rows to keep, which columns to return, how to sort them and how many to take. You write those parts in one order, but PostgreSQL evaluates them in another: FROM, then WHERE, then SELECT, then ORDER BY, then LIMIT. Knowing that order explains several errors that otherwise look arbitrary.
Helps to know first: Install PostgreSQL and learn the environment
On this page
Every query on this page runs against the practice database. Connect with psql shop and type them as you read.
The shape of a query
SELECT name, category, price -- which columns
FROM products -- which table
WHERE category = 'Accessories' -- which rows
ORDER BY price DESC; -- in what order
name | category | price
---------------------+-------------+---------
Mechanical keyboard | Accessories | 4500.00
USB-C hub | Accessories | 2499.00
Laptop stand | Accessories | 1899.00
Wireless mouse | Accessories | 1200.00
Cable organiser | Accessories | 499.00
(5 rows)
SELECTlists the columns you want, or expressions computed from them.SELECT *means every column, which is handy while exploring but best avoided in application code, where a new column would silently change the result.FROMnames the table.WHEREkeeps only the rows for which the condition is true.ORDER BYsorts: ascending by default,DESCfor descending.
Add LIMIT to take only the first few rows of the sorted result:
SELECT name, price FROM products ORDER BY price DESC LIMIT 3;
name | price
-----------------------------+----------
27-inch monitor | 18999.00
Office chair | 14500.00
Noise-cancelling headphones | 12999.00
LIMIT without ORDER BY is almost always a bug: you get some three rows, not the top three. Rows have no order until you give them one.
Written order versus evaluated order
You write SELECT … FROM … WHERE … ORDER BY … LIMIT. PostgreSQL evaluates it in a different order:
| Step | Clause | What happens |
|---|---|---|
| 1 | FROM | Gather the rows of the table (or tables) |
| 2 | WHERE | Throw away rows whose condition is not true |
| 3 | SELECT | Compute the output columns for the rows that are left |
| 4 | ORDER BY | Sort the output |
| 5 | LIMIT | Keep only the first n rows |
Grouping steps fit between WHERE and SELECT; they arrive in Aggregation and grouping.
PredictUsing an alias in WHERE
You compute a price including 18% tax, name it, and filter on the name:
SELECT name, price * 1.18 AS price_with_tax
FROM products
WHERE price_with_tax > 10000;Does it work?
No. PostgreSQL replies:
ERROR: column "price_with_tax" does not existWHERE runs at step 2; the alias is only created at step 3, in SELECT. At the moment WHERE runs, price_with_tax does not exist yet. Repeat the expression instead: WHERE price * 1.18 > 10000.
ORDER BY runs at step 4, after SELECT, so there the alias works:
SELECT name, price * 1.18 AS price_with_tax FROM products ORDER BY price_with_tax DESC LIMIT 3; name | price_with_tax
-----------------------------+----------------
27-inch monitor | 22418.8200
Office chair | 17110.0000
Noise-cancelling headphones | 15338.8200Sorting and empty values
When the column you sort by has NULLs, they go last in ascending order and first in descending order:
SELECT name, city FROM customers ORDER BY city;
name | city
---------------+----------
Farhan Ali | Karachi
Ben Okafor | Lagos
Asha Rao | Pune
Divya Iyer | Pune
Grace Kim | Seoul
Chen Wei | Shanghai
Hugo Martin |
Elena Petrova |
Asha and Divya share a city, and so do the two customers with no city. Rows that tie on every sort column can come back in any order. If the order matters, add another column to break the tie: ORDER BY city, name.
Check yourself
In what order does PostgreSQL evaluate
FROM,WHERE,SELECT,ORDER BYandLIMIT?Show answer
FROM, thenWHERE, thenSELECT, thenORDER BY, thenLIMIT.Why can
ORDER BYuse a column alias defined inSELECTwhenWHEREcannot?Show answer
ORDER BYis evaluated afterSELECThas computed the output columns, so the alias exists.WHEREis evaluated beforeSELECT, when it does not.What does
SELECT * FROM orders LIMIT 5return?Show answer
Five rows of the table, but no particular five: without
ORDER BYthe order is unspecified, so “the first five” means nothing. AddORDER BY ordered_at DESCto get the five newest.
Finished reading?
Saved in this browser only.
Sources
Where each claim on this page comes from.
- 1.PostgreSQL documentation: SELECTPrimary· Description, and WHERE Clause
The order in which SELECT is processed; WHERE keeps only rows for which the condition returns true; without ORDER BY, rows come back in whatever order is fastest.
- 2.PostgreSQL documentation: 7.5 Sorting Rows (ORDER BY)Primary· §7.5 Sorting Rows (ORDER BY)
Without ORDER BY the order is unspecified and must not be relied on; ORDER BY can use an output column's name; NULLs sort last in ascending order and first in descending order by default.
Go further
What to read next, and why it is worth the time.
- 1.PostgreSQL documentation: SELECTPrimary· Description
The ten-step list of how PostgreSQL processes a query. Read it once now and again after the joins and grouping topics.
Applies to PostgreSQL 18. Draft: not yet fact-checked end to end.