SQL exercises with solutions: SELECT, aliases and DISTINCT
Updated on
SELECT picks the columns to show; AS renames a column, DISTINCT removes duplicates. These 4 game exercises are level 1, followed by 5 exercises from the course; they use the syntax of SQLite, SpeedQL’s SQL engine.
Tip: List the columns you need rather than SELECT *: the result is easier to read and faster.
Read the “SELECT, aliases, DISTINCT” card in the cheat sheet
Exercise 1
Show every column and every row of the employees table.
| id | name | department | salary |
|---|---|---|---|
| 1 | Alice | Finance | 32000 |
| 2 | Bob | IT | 41000 |
| 3 | Claire | Finance | 38000 |
| 4 | David | HR | 29000 |
Show the hint
Topics to use: SELECT, aliases, DISTINCT.
Query structure:
SELECT *
FROM …Show the solution
SELECT *
FROM employees;Expected result (4 rows):
| id | name | department | salary |
|---|---|---|---|
| 1 | Alice | Finance | 32000 |
| 2 | Bob | IT | 41000 |
| 3 | Claire | Finance | 38000 |
| 4 | David | HR | 29000 |
Exercise 2
Show only the name and the salary of every employee.
| id | name | department | salary |
|---|---|---|---|
| 1 | Alice | Finance | 32000 |
| 2 | Bob | IT | 41000 |
| 3 | Claire | Finance | 38000 |
| 4 | David | HR | 29000 |
Show the hint
Topics to use: SELECT, aliases, DISTINCT.
Query structure:
SELECT …, …
FROM …Show the solution
SELECT name, salary
FROM employees;Expected result (4 rows):
| name | salary |
|---|---|
| Alice | 32000 |
| Bob | 41000 |
| Claire | 38000 |
| David | 29000 |
Exercise 3
Show the employees' names in a column called employee, and their salaries in a column called annual_salary.
| id | name | department | salary |
|---|---|---|---|
| 1 | Alice | Finance | 32000 |
| 2 | Bob | IT | 41000 |
| 3 | Claire | Finance | 38000 |
| 4 | David | HR | 29000 |
Show the hint
Topics to use: SELECT, aliases, DISTINCT.
Query structure:
SELECT … AS …, … AS …
FROM …Show the solution
SELECT name AS employee, salary AS annual_salary
FROM employees;Expected result (4 rows):
| employee | annual_salary |
|---|---|
| Alice | 32000 |
| Bob | 41000 |
| Claire | 38000 |
| David | 29000 |
Exercise 4
Show the list of product categories, without duplicates.
| id | name | category | price | stock |
|---|---|---|---|---|
| 1 | Keyboard | Office | 25 | 40 |
| 2 | Mouse | Office | 15 | 0 |
| 3 | Screen | Display | 180 | 12 |
| 4 | Headset | Audio | 60 | 8 |
| 5 | Webcam | Office | 45 | 0 |
| 6 | Speaker | Audio | 35 | 25 |
Show the hint
Topics to use: SELECT, aliases, DISTINCT.
Query structure:
SELECT DISTINCT …
FROM …Show the solution
SELECT DISTINCT category
FROM products;Expected result (3 rows):
| category |
|---|
| Office |
| Display |
| Audio |
More exercises: level 1 of the SQL course, “Reading a table with SELECT”
These 5 exercises come from level 1 of the course, on other tables. Each one has written hints and its solution, folded by default.
Exercise 5
Show every column of the movies table.
| id | title | genre | year | duration | rating | director_id |
|---|---|---|---|---|---|---|
| 1 | Night Train | Thriller | 2015 | 118 | 7.8 | 1 |
| 2 | Blue Harbor | Drama | 2018 | 102 | 7.1 | 2 |
| 3 | Paper Moon City | Comedy | 2012 | 95 | 6.4 | 5 |
| 4 | Silent Peak | Drama | 2020 | 131 | 8.2 | 3 |
| 5 | Last Signal | Sci-Fi | 2019 | 142 | 7.5 | 1 |
| 6 | Summer Keys | Comedy | 2016 | 88 | 5.9 | 4 |
| 7 | Iron Garden | Sci-Fi | 2021 | 125 | 8 | 3 |
| 8 | Dust and Gold | Western | 2014 | 110 | 6.8 | 2 |
| 9 | The Quiet Hour | Drama | 2022 | 97 | 7.4 | 5 |
| 10 | Deep Current | Thriller | 2017 | 105 | 6.9 | NULL |
Show the hints
Hint: The star * replaces the list of all the columns.
Show the solution
SELECT *
FROM movies;Expected result (10 rows):
| id | title | genre | year | duration | rating | director_id |
|---|---|---|---|---|---|---|
| 1 | Night Train | Thriller | 2015 | 118 | 7.8 | 1 |
| 2 | Blue Harbor | Drama | 2018 | 102 | 7.1 | 2 |
| 3 | Paper Moon City | Comedy | 2012 | 95 | 6.4 | 5 |
| 4 | Silent Peak | Drama | 2020 | 131 | 8.2 | 3 |
| 5 | Last Signal | Sci-Fi | 2019 | 142 | 7.5 | 1 |
| 6 | Summer Keys | Comedy | 2016 | 88 | 5.9 | 4 |
| 7 | Iron Garden | Sci-Fi | 2021 | 125 | 8 | 3 |
| 8 | Dust and Gold | Western | 2014 | 110 | 6.8 | 2 |
| 9 | The Quiet Hour | Drama | 2022 | 97 | 7.4 | 5 |
| 10 | Deep Current | Thriller | 2017 | 105 | 6.9 | NULL |
SELECT * is the quickest way to discover what a table contains.
Exercise 6
Show the title and genre of each movie.
| id | title | genre | year | duration | rating | director_id |
|---|---|---|---|---|---|---|
| 1 | Night Train | Thriller | 2015 | 118 | 7.8 | 1 |
| 2 | Blue Harbor | Drama | 2018 | 102 | 7.1 | 2 |
| 3 | Paper Moon City | Comedy | 2012 | 95 | 6.4 | 5 |
| 4 | Silent Peak | Drama | 2020 | 131 | 8.2 | 3 |
| 5 | Last Signal | Sci-Fi | 2019 | 142 | 7.5 | 1 |
| 6 | Summer Keys | Comedy | 2016 | 88 | 5.9 | 4 |
| 7 | Iron Garden | Sci-Fi | 2021 | 125 | 8 | 3 |
| 8 | Dust and Gold | Western | 2014 | 110 | 6.8 | 2 |
| 9 | The Quiet Hour | Drama | 2022 | 97 | 7.4 | 5 |
| 10 | Deep Current | Thriller | 2017 | 105 | 6.9 | NULL |
Show the hints
Hint 1 · lead: List the columns you want right after SELECT.
Hint 2 · method: Separate the two columns with a comma: SELECT title, genre …
Show the solution
SELECT title, genre
FROM movies;Expected result (10 rows):
| title | genre |
|---|---|
| Night Train | Thriller |
| Blue Harbor | Drama |
| Paper Moon City | Comedy |
| Silent Peak | Drama |
| Last Signal | Sci-Fi |
| Summer Keys | Comedy |
| Iron Garden | Sci-Fi |
| Dust and Gold | Western |
| The Quiet Hour | Drama |
| Deep Current | Thriller |
Columns appear in the order you write them.
Exercise 7
Show the title of each movie in a column named film, and its duration in a column named minutes.
| id | title | genre | year | duration | rating | director_id |
|---|---|---|---|---|---|---|
| 1 | Night Train | Thriller | 2015 | 118 | 7.8 | 1 |
| 2 | Blue Harbor | Drama | 2018 | 102 | 7.1 | 2 |
| 3 | Paper Moon City | Comedy | 2012 | 95 | 6.4 | 5 |
| 4 | Silent Peak | Drama | 2020 | 131 | 8.2 | 3 |
| 5 | Last Signal | Sci-Fi | 2019 | 142 | 7.5 | 1 |
| 6 | Summer Keys | Comedy | 2016 | 88 | 5.9 | 4 |
| 7 | Iron Garden | Sci-Fi | 2021 | 125 | 8 | 3 |
| 8 | Dust and Gold | Western | 2014 | 110 | 6.8 | 2 |
| 9 | The Quiet Hour | Drama | 2022 | 97 | 7.4 | 5 |
| 10 | Deep Current | Thriller | 2017 | 105 | 6.9 | NULL |
Show the hints
Hint 1 · lead: An alias goes right after the column it renames.
Hint 2 · method: Add AS film after title, and AS minutes after duration.
Show the solution
SELECT title AS film, duration AS minutes
FROM movies;Expected result (10 rows):
| film | minutes |
|---|---|
| Night Train | 118 |
| Blue Harbor | 102 |
| Paper Moon City | 95 |
| Silent Peak | 131 |
| Last Signal | 142 |
| Summer Keys | 88 |
| Iron Garden | 125 |
| Dust and Gold | 110 |
| The Quiet Hour | 97 |
| Deep Current | 105 |
An alias only changes the displayed name: the table itself is not modified.
Exercise 8
Show the name and price of each dish, plus the price for two people in a column named price_for_two.
| id | name | category | price | calories | vegetarian | chef_id |
|---|---|---|---|---|---|---|
| 1 | Ratatouille | main | 14.5 | 320 | yes | 1 |
| 2 | Beef burger | main | 16 | 780 | no | 2 |
| 3 | Caesar salad | starter | 9.5 | 410 | no | 1 |
| 4 | Tomato soup | starter | 7 | 180 | yes | 3 |
| 5 | Chocolate cake | dessert | 6.5 | 520 | yes | 2 |
| 6 | Lemon tart | dessert | 6 | 430 | yes | 3 |
| 7 | Grilled salmon | main | 19 | 560 | no | 1 |
| 8 | Onion soup | starter | 8 | 290 | yes | 2 |
Show the hints
Hint 1 · lead: A calculation can be written directly in the SELECT list, like a column.
Hint 2 · method: A computed column: price * 2 AS price_for_two.
Show the solution
SELECT name, price, price * 2 AS price_for_two
FROM dishes;Expected result (8 rows):
| name | price | price_for_two |
|---|---|---|
| Ratatouille | 14.5 | 29 |
| Beef burger | 16 | 32 |
| Caesar salad | 9.5 | 19 |
| Tomato soup | 7 | 14 |
| Chocolate cake | 6.5 | 13 |
| Lemon tart | 6 | 12 |
| Grilled salmon | 19 | 38 |
| Onion soup | 8 | 16 |
The calculation is done again for every row of the table.
Exercise 9
For each flight, show the airline, the flight's revenue (revenue: price × seats sold) and the revenue lost to empty seats (lost_revenue: price × empty seats).
| id | airline | origin | dest | departs | duration_min | price | seats_sold | capacity |
|---|---|---|---|---|---|---|---|---|
| 1 | SkyJet | CDG | MAD | 2025-06-01 08:10 | 125 | 89 | 150 | 180 |
| 2 | AirNova | CDG | LIS | 2025-06-01 11:40 | 155 | 120 | 160 | 170 |
| 3 | BlueWing | LYS | FCO | 2025-06-02 07:30 | 95 | 75 | 110 | 150 |
| 4 | SkyJet | MAD | CDG | 2025-06-02 18:20 | 120 | 95 | 170 | 180 |
| 5 | AirNova | BER | CDG | 2025-06-03 09:05 | 110 | 105 | 140 | 160 |
| 6 | BlueWing | NCE | BER | 2025-06-03 13:50 | 130 | 140 | 90 | 150 |
| 7 | SkyJet | CDG | FCO | 2025-06-04 06:45 | 135 | 99 | 175 | 180 |
| 8 | AirNova | LIS | MAD | 2025-06-04 16:15 | 75 | 65 | 60 | 120 |
| 9 | BlueWing | FCO | LYS | 2025-06-05 20:30 | 100 | 82 | 130 | 150 |
| 10 | SkyJet | CDG | BER | 2025-06-05 10:00 | 105 | 110 | 120 | 180 |
| 11 | AirNova | MAD | LIS | 2025-06-06 12:25 | 80 | 70 | 95 | 120 |
| 12 | BlueWing | LYS | MAD | 2025-06-06 15:40 | 115 | 79 | 100 | 150 |
Show the hints
Hint 1 · lead: First work out the number of empty seats, then multiply it by the price. Mind the order of operations.
Hint 2 · method: Empty seats are capacity - seats_sold: put this calculation in parentheses before multiplying it by price.
Show the solution
SELECT airline,
price * seats_sold AS revenue,
price * (capacity - seats_sold) AS lost_revenue
FROM flights;Expected result (12 rows):
| airline | revenue | lost_revenue |
|---|---|---|
| SkyJet | 13350 | 2670 |
| AirNova | 19200 | 1200 |
| BlueWing | 8250 | 3000 |
| SkyJet | 16150 | 950 |
| AirNova | 14700 | 2100 |
| BlueWing | 12600 | 8400 |
| SkyJet | 17325 | 495 |
| AirNova | 3900 | 3900 |
| BlueWing | 10660 | 1640 |
| SkyJet | 13200 | 6600 |
| AirNova | 6650 | 1750 |
| BlueWing | 7900 | 3950 |
Without parentheses, price * capacity - seats_sold computes (price × capacity) − seats_sold: multiplication comes before subtraction.
Practice with automatic checking
In SpeedQL, you write your query and it is checked straight away, on these tables and then on a hidden dataset.