Skip to content

Selecting and filtering

Reading is the most common thing you do with a database, and SELECT is how you do it. A SELECT describes which columns you want, which rows qualify, in what order, and how many. The server returns a result set — zero or more rows — without changing anything on disk.

These examples assume the authors table is populated with a handful of rows from the insert lesson.

List the columns you want after SELECT. Use * only for quick exploration; in real code, name the columns so the result stays stable even if someone adds a column later.

SELECT id, name, born FROM authors;
id | name | born
----+-----------------+------
1 | Mira Castellan | 1971
2 | Devon Reyes | 1985
3 | Priya Anand | 1990
4 | Tomas Holt | 1962
(4 rows)

WHERE keeps only the rows whose condition is true. You can compare with =, <, >, <=, >=, and combine conditions with AND and OR.

SELECT name, born
FROM authors
WHERE born >= 1980 AND born < 1995;
name | born
-------------+------
Devon Reyes | 1985
Priya Anand | 1990
(2 rows)

IN checks membership in a list, BETWEEN is an inclusive range, and LIKE matches text patterns. LIKE is case-sensitive; PostgreSQL also offers ILIKE for a case-insensitive match. In patterns, % matches any run of characters and _ matches exactly one.

SELECT name, born
FROM authors
WHERE born BETWEEN 1960 AND 1980
AND name ILIKE '%a%';
name | born
----------------+------
Mira Castellan | 1971
Tomas Holt | 1962
(2 rows)

NULL means “unknown”, so it does not behave like an ordinary value. You cannot test it with =; use IS NULL and IS NOT NULL instead. Suppose one author has no recorded birth year.

SELECT name FROM authors WHERE born IS NULL;

ORDER BY sorts the result; add DESC for descending. LIMIT caps the number of rows, and OFFSET skips rows from the top — together they let you page through a large table.

SELECT name, born
FROM authors
ORDER BY born DESC
LIMIT 2 OFFSET 1;
name | born
-------------+------
Devon Reyes | 1985
Mira Castellan | 1971
(2 rows)

In pgAdmin: run any of these in the Query Tool; results appear in the Data Output grid below, where you can also sort columns by clicking their headers.

  • NULL uses three-valued logic: a comparison against NULL is neither true nor false but unknown, so such rows are excluded by WHERE. Always use IS NULL rather than = NULL.
  • LIMIT without an ORDER BY returns an arbitrary subset — the server may return rows in any order, and that order can change between runs. Always pair LIMIT with a deterministic ORDER BY.
  • ILIKE is convenient but cannot use a plain index efficiently; for heavy text search, look into trigram indexes or full-text search later in the course.
  • Selecting only the columns you need keeps result sets small and your code resilient to schema changes.
How do you correctly find rows where the born column is unknown?
What is true about LIMIT without an ORDER BY?
Which operator does a case-insensitive pattern match in PostgreSQL?
What does OFFSET 1 do in a SELECT?