Session 4 · Querying data with SELECT#
The big idea#
SELECT is how you ask the database a question. You say which columns you want and which
table to read them from. You can rename columns, calculate new ones, sort the result and remove
repeats. The table itself is never changed: SELECT only reads.
Everyday example: a railway enquiry counter. You do not carry the whole timetable home. You ask
“trains from Chennai, show name and departure time, earliest first,” and the clerk reads out just that.
SELECT name, departure FROM trains ORDER BY departure is the same request in SQL.
The practice queries#
Each query below was run against the movie database from code/00-setup.sql. The \echo lines just
print a label so you can match each result to its query.
\echo '-- one column'
SELECT title FROM movies;
\echo '-- several columns, with aliases'
SELECT title AS film, year AS released FROM movies;
\echo '-- computed column'
SELECT title, year, 2026 - year AS age_in_years FROM movies;
\echo '-- ORDER BY, newest first, then title'
SELECT title, year FROM movies ORDER BY year DESC, title ASC;
\echo '-- DISTINCT removes repeats'
SELECT DISTINCT genre FROM movies ORDER BY genre;
\echo '-- DISTINCT on two columns'
SELECT DISTINCT genre, year FROM movies WHERE year = 1995 ORDER BY genre;
Real output#
-- one column
title
-------------------
Nayakan
Thalapathi
Baasha
Muthu
Sivaji
Pariyerum Perumal
Kaithi
Soorarai Pottru
Karnan
Vikram
Untitled Project
(11 rows)
-- several columns, with aliases
film | released
-------------------+----------
Nayakan | 1987
Thalapathi | 1991
Baasha | 1995
Muthu | 1995
Sivaji | 2007
Pariyerum Perumal | 2018
Kaithi | 2019
Soorarai Pottru | 2020
Karnan | 2021
Vikram | 2022
Untitled Project | 2026
(11 rows)
-- computed column
title | year | age_in_years
-------------------+------+--------------
Nayakan | 1987 | 39
Thalapathi | 1991 | 35
Baasha | 1995 | 31
Muthu | 1995 | 31
Sivaji | 2007 | 19
Pariyerum Perumal | 2018 | 8
Kaithi | 2019 | 7
Soorarai Pottru | 2020 | 6
Karnan | 2021 | 5
Vikram | 2022 | 4
Untitled Project | 2026 | 0
(11 rows)
-- ORDER BY, newest first, then title
title | year
-------------------+------
Untitled Project | 2026
Vikram | 2022
Karnan | 2021
Soorarai Pottru | 2020
Kaithi | 2019
Pariyerum Perumal | 2018
Sivaji | 2007
Baasha | 1995
Muthu | 1995
Thalapathi | 1991
Nayakan | 1987
(11 rows)
-- DISTINCT removes repeats
genre
--------
Action
Comedy
Crime
Drama
(5 rows)
-- DISTINCT on two columns
genre | year
--------+------
Action | 1995
Comedy | 1995
(2 rows)
What each part did#
SELECT title FROM moviesreturns one column from every row.SELECT *returns all columns; it is handy in a console but in application code list the columns you need, so a new column added later cannot break your program.ASgives a column a nicer name in the result (film,released). The stored column is not renamed.Calculated columns:
2026 - year AS age_in_yearsis computed for each row on the fly.ORDER BY year DESC, title ASCsorts by year first, then breaks ties by title. WithoutORDER BYthe order of rows is not guaranteed.SELECT DISTINCT genreshows each genre once.DISTINCTon two columns removes duplicate pairs; the last query shows Comedy and Action for 1995, each once.
Read the diagram above as the order the database thinks in: table first, then rows, then columns,
then sorting. That is why an alias defined in SELECT can be used in ORDER BY but not in WHERE.
Common mistakes#
Forgetting the semicolon in
psql. The prompt changes tocourse-#and waits for more. Type;and Enter.Trusting row order without
ORDER BY. It looks sorted on your laptop and changes in production.Using
SELECT *in application code. You pull unneeded data, and your code breaks when the table changes.Single versus double quotes.
'Action'is a text value;"Action"is an identifier (a column name). Mixing them gives “column does not exist”.Thinking
DISTINCTapplies to one column. It applies to the whole row you selected.
Hands-on exercises#
Exercise 1. Show every movie’s title and rating, best rated first. What happens to the movie
that has no rating?
Solution
SELECT title, rating FROM movies ORDER BY rating DESC;
In PostgreSQL NULL sorts first in a descending sort, so “Untitled Project” appears at the top, then Nayakan (9.0).
Use ORDER BY rating DESC NULLS LAST to push it to the bottom.
Exercise 2. List the different release years once each, oldest first.
Solution
SELECT DISTINCT year FROM movies ORDER BY year;
1995 appears once even though two movies came out that year.
Exercise 3. Show title as film and a new column decade that is the year rounded down to
the decade (1987 gives 1980).
Solution
SELECT title AS film, (year / 10) * 10 AS decade FROM movies ORDER BY decade, film;
Both numbers are integers, so year / 10 drops the fraction (198.7 becomes 198), and * 10 brings
it back to 1980.
Practice#
Take the Session 4 quiz (SELECT, aliases, ORDER BY, DISTINCT). The original DB-TASK-001 on the DVD Rental database is in the reference section of the course.