Databases & SQL Interview Questions: Querying Practice
Reviewed by Mark Dickie · Last updated
SQL querying is the practice of writing declarative statements to retrieve and transform data stored in a relational database. For interviews, you need fluency with JOINs across multiple tables, GROUP BY with aggregation, subqueries and CTEs, and window functions such as ROW_NUMBER and RANK. You should also know how indexes affect performance and be able to read an EXPLAIN plan to spot full table scans.
What types of SQL queries come up in interviews?
| Concept | What interviewers test | Common tasks |
|---|---|---|
| INNER / LEFT JOIN | Matching rows across tables | Find customers with no orders |
| GROUP BY + HAVING | Aggregation with filtering | Count orders per user, keep only > 5 |
| Window functions | Ranking and running totals | Top 3 products per category |
| Subqueries / CTEs | Breaking logic into steps | Compare salary to department average |
| Set operations | Combining result sets | UNION of two customer lists |
How do you approach a SQL interview question?
- Clarify the schema and expected output before writing anything. Ask which columns the result should contain and whether duplicates matter.
- Identify the granularity of the output: one row per what?
- Pick the JOINs first, then add filtering and aggregation on top.
- Test with edge cases like NULL values or ties in ranking functions.
- If asked about performance, check the WHERE clause for non-sargable predicates and mention whether an index would help.
Key facts
- Tarmac has 66 Databases & SQL interview questions on this topic, 10 of them on this page, at difficulty 1–3 of 5.
- Tarmac tracked 8,648 job postings asking for Databases & SQL in August 2026.
- Roles asking for Databases & SQL advertise a median base salary of US$166,400, across 1,383 job postings as of August 2026.
- Tarmac last reviewed these Databases & SQL interview questions on 7 September 2026.
At a glance
| Questions | 10 shown · 66 in the bank |
|---|---|
| Difficulty | 1–3 of 5 |
| Formats | Multiple choice, True / false, Code output, Coding exercise, Fill in the blank, Find the bug, Short answer |
| Interactive | 1 run your code against tests, in the app |
What you'll review
- select basics
- joins
- window functions
- aggregation
Practice questions
Try one before you open the answer. Pick an option and press Check; it's marked on the spot.
Databases & SQL/querying/select-basics
Which keyword removes duplicate rows from a SELECT result set?#
Options
Show answer
DISTINCT removes duplicate rows from a SELECT result set. Writing SELECT DISTINCT collapses rows that are identical across all selected columns into a single row. UNIQUE is a column or table constraint rather than a query keyword, and GROUP BY aggregates rows instead of simply de-duplicating them.
SELECT DISTINCT collapses rows that are identical across all selected columns into one. UNIQUE is a column/table constraint, not a query keyword, and GROUP BY aggregates rather than simply de-duplicating.
Databases & SQL/querying/joins
For an INNER JOIN, swapping which table is written first (A JOIN B vs B JOIN A) changes which rows appear in the result.#
Options
Show answer
False. INNER JOIN is commutative with respect to its result set, so A JOIN B and B JOIN A return the same rows (column ordering aside). Swapping which table is written first changes nothing about which rows appear. This is not true for outer joins, where LEFT JOIN and RIGHT JOIN keep different unmatched sides.
INNER JOIN is commutative with respect to its result set: A INNER JOIN B ON … and B INNER JOIN A ON … return the same rows (column ordering aside). This is not true for outer joins — LEFT JOIN and RIGHT JOIN keep different unmatched sides.
Databases & SQL/querying/window-functions
You can filter rows using a window function directly in the WHERE clause, e.g. WHERE ROW_NUMBER() OVER (ORDER BY id) <= 5.#
Options
Show answer
False. Window functions are evaluated after WHERE and GROUP BY but before ORDER BY, so they cannot appear in a WHERE clause — the engine hasn't computed them yet at that stage. To filter on a window function result, wrap the query in a subquery or CTE and apply WHERE in the outer query.
Window functions are evaluated after WHERE and GROUP BY but before ORDER BY, so they cannot appear in a WHERE clause — the engine hasn't computed them yet at that stage. To filter on a window function result, wrap the query in a subquery or CTE and apply WHERE in the outer query.
Databases & SQL/querying/select-basics
Given employees(name, salary) with rows (Ann, 90), (Bo, 70), (Cy, 90), (Di, 50), what does this query return?#
SELECT name, salary
FROM employees
WHERE salary >= 70
ORDER BY salary DESC, name ASC
LIMIT 2;Options
Show answer
(Ann, 90), (Cy, 90)
WHERE salary >= 70 drops Di (50). The remaining three sort by salary DESC first, tying Ann and Cy at 90; the secondary name ASC orders Ann before Cy. LIMIT 2 then keeps the top two: (Ann, 90), (Cy, 90).
Databases & SQL/querying/aggregation
The users table has columns id (INTEGER) and email (TEXT). Write a query returning each email address that appears more than once, with columns email and cnt (how many times it appears), ordered by cnt descending, then email ascending.#
Starter code
-- Return: email, cnt (count > 1), ordered by cnt DESC, email ASC
SELECT
Your solution must pass
- finds both duplicated emails with their counts
This one is written and run, not read. Solve it in the app and your code is executed against these tests and the hidden ones.
Databases & SQL/querying/joins
To keep every row from the left table even when there is no match, use customers c _____ JOIN orders o _____ o.customer_id = c.id.#
Show answer
To keep every row from the left table even when there is no match, use customers c **LEFT** JOIN orders o **ON** o.customer_id = c.id.
LEFT JOIN (synonym LEFT OUTER JOIN) preserves all left-hand rows, padding unmatched right-hand columns with NULL. The ON clause states the join predicate that decides which rows match — distinct from a later WHERE, which filters the joined result.
Databases & SQL/querying/joins
A LEFT JOIN between customers (left) and orders (right) returns a customer who has placed no orders. What appears in that row's orders columns?#
Options
Show answer
Every orders column holds NULL. A LEFT JOIN keeps each left-hand row even when no right-hand row matches the ON condition, filling the unmatched right-hand columns with NULL rather than omitting the row or substituting 0 or empty strings. This is exactly why a WHERE orders.id IS NULL filter after a LEFT JOIN finds customers who have placed no orders.
A LEFT JOIN keeps every left-hand row even when no right-hand row matches the ON condition; the unmatched right-hand columns are filled with NULL. This is exactly why a WHERE orders.id IS NULL filter after a LEFT JOIN finds customers with no orders.
Databases & SQL/querying/joins
customers(id, name) has (1, Ann), (2, Bo), (3, Cy). orders(customer_id, amount) has (1, 10), (1, 20), (2, 5). How many rows does this query return?#
SELECT c.name, o.amount
FROM customers c
INNER JOIN orders o ON o.customer_id = c.id;Options
Show answer
3 rows
An INNER JOIN emits one row per matching pair. Ann (id 1) matches two orders and Bo (id 2) matches one, giving 3 rows; Cy (id 3) has no orders and is excluded entirely. The result is (Ann, 10), (Ann, 20), (Bo, 5).
Databases & SQL/querying/joins
This is meant to be a LEFT JOIN listing every customer and their order count, but customers with no orders are dropped. Which line causes that?#
SELECT c.name, COUNT(o.id) AS order_count
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.status = 'shipped'
GROUP BY c.name;Show answer
The bug is on line 4.
A WHERE predicate on the right-hand table runs after the join, and o.status = 'shipped' is never true for the NULL columns of an unmatched customer, so those rows are filtered out — silently turning the LEFT JOIN into an inner join. The fix is to move the condition into the join itself (LEFT JOIN orders o ON o.customer_id = c.id AND o.status = 'shipped') so unmatched customers survive.
Databases & SQL/querying/window-functions
Both GROUP BY and a window function like AVG(salary) OVER (...) can compute an average per group. What is the key difference in what each returns?#
Show answer
GROUP BY collapses each group down to a single output row, so you lose the individual rows and can only emit aggregates and the grouping columns. A window function computes the aggregate over a partition but keeps every input row, attaching the group-level value to each detail row alongside its own columns. So if you want each employee's row to also show their department average, you use a window function; GROUP BY would give you one row per department instead.
GROUP BY reduces N rows in a group to one summary row, discarding the detail. A window function (OVER (...)) evaluates the same aggregate across a partition but does not collapse rows — every original row survives and gets the computed value appended. That row-preserving behaviour is exactly why window functions are reached for when you need both the detail and a group-level metric (average, total, rank) in the same result set.
Sources
The official documentation these questions are checked against:
Related interview questions
Job market
See databases-sql salaries and hiring demand from live job postings.
The other 56 questions
This page shows 10 and marks what you pick. That's as far as a page can go. A free account opens the other 56 and keeps every answer. What you miss comes back until it's right: after a day, then at longer gaps.
Free · the whole bank · 100 marked answers per 30 days · written feedback on the paid plan