SQL interview questions, with the queries written out.
Practice two SQL questions that come up in data and developer interviews, free, with the full queries explained.
Published November 1, 2026
SQL interviews usually start with a query you write on the spot, then move to a messier real-world task. Here’s one of each.
Free question 1 (query): Customers with three or more orders
You have two tables. customers (customer_id, name) and orders (order_id, customer_id, order_date, amount). Return each customer who placed at least 3 orders in 2025, with their number of orders and total spent, highest spender first.
Model answer
SELECT c.customer_id,
c.name,
COUNT(*) AS order_count,
SUM(o.amount) AS total_spent
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_date >= '2025-01-01'
AND o.order_date < '2026-01-01'
GROUP BY c.customer_id, c.name
HAVING COUNT(*) >= 3
ORDER BY total_spent DESC;
Walk through it out loud:
- JOIN connects each order to its customer. An inner join is right here, because a customer with no orders can’t have three.
- WHERE filters rows before grouping, so only 2025 orders are counted.
- The date range uses “on or after January 1, 2025” and “before January 1, 2026”. That catches every moment of December 31, even if order_date stores a time. Writing “<= ‘2025-12-31’” would miss orders placed later that day.
- GROUP BY makes one row per customer. Include name too, since it’s in the SELECT.
- HAVING filters after grouping. You can’t use COUNT in WHERE, because the count doesn’t exist until the rows are grouped.
Follow-ups to expect: “What if you also need customers with zero orders?” Use a LEFT JOIN, move the date condition into the ON clause so customers without 2025 orders aren’t dropped, and count o.order_id instead of every row. “How would you make this fast on millions of rows?” An index on orders (customer_id, order_date) helps.
What interviewers listen for: you explain WHERE versus HAVING, you handle the date range carefully, and you talk through edge cases before being asked.
Free question 2 (data cleanup): Find and remove duplicates
A users table (user_id, email, created_at) has duplicate accounts, some with the same email in different capitals, like Sam@Mail.com and sam@mail.com. Find the duplicates, then delete them, keeping the oldest account for each email.
Model answer
Step 1: find them. Compare emails in lower case so capitals don’t hide duplicates.
SELECT LOWER(email) AS email_key, COUNT(*) AS copies
FROM users
GROUP BY LOWER(email)
HAVING COUNT(*) > 1;
Step 2: rank each copy. ROW_NUMBER gives 1 to the oldest row for each email, 2 to the next, and so on. Adding user_id to the ORDER BY breaks ties if two rows have the same created_at.
WITH ranked AS (
SELECT user_id,
ROW_NUMBER() OVER (
PARTITION BY LOWER(email)
ORDER BY created_at, user_id
) AS rn
FROM users
)
SELECT user_id FROM ranked WHERE rn > 1;
Step 3: delete, carefully. Run the SELECT above first and check the rows. Then swap the last line for a delete:
WITH ranked AS (
SELECT user_id,
ROW_NUMBER() OVER (
PARTITION BY LOWER(email)
ORDER BY created_at, user_id
) AS rn
FROM users
)
DELETE FROM users
WHERE user_id IN (SELECT user_id FROM ranked WHERE rn > 1);
This works in PostgreSQL and SQL Server. MySQL may refuse to delete from a table it’s reading in the same statement, so there you’d first save the IDs in a temporary table, then delete using that.
Then say what a careful person adds:
- Run it inside a transaction, or back up the table first, so you can undo a mistake.
- Check whether other tables point to the duplicate user_ids, like orders. Those may need moving to the kept account first.
- Stop it happening again: add a unique index on the lower-case email.
What interviewers listen for: you check before deleting, you think about the tie-breaker and related tables, and you fix the cause, not just the symptom.
The full SQL interview guide
One printable PDF. Part 1 is the prep section: what to wear, when to arrive or log in, key topics to review for this role, questions to ask, talking about pay, a story bank, the day before and the day itself, and a thank you note. Part 2 is 20 questions for this role, each with a possible answer and lined space for your notes. A checklist for the night before is included. Print it on US Letter and write in it.
- A full prep section: what to wear, when to arrive or log in, key topics to review, questions to ask, talking about pay, a story bank, the day before and the day itself, and a thank you note
- 6 query writing questions: window functions, common table expressions, self joins, date ranges, handling NULLs and top N per group
- 4 concept questions: indexes, join types, normalization and transactions
- 5 behavioural questions with sample STAR answers, plus lines for your own stories
- 5 situational questions, such as a slow report or numbers that don't match
- A checklist for the night before
One PDF, $24 CAD / $17 USD, paid once on this page and emailed to you. Visitors in Canada pay $24 CAD. Everyone else pays $17 USD.
About these questions
Are these SQL interview questions for jobs in Canada?
Yes. SQL questions come up in Canadian interviews for data analyst, business analyst, developer and data engineer roles. The queries here use standard SQL that runs in PostgreSQL and SQL Server, and in MySQL with the small change noted.
Is there a full interview guide?
Yes. The full printable SQL interview guide is $24 CAD / $17 USD. You pay on this page and we email you the PDF. It has a prep section (what to wear, when to arrive or log in, key topics for this role, questions to ask, talking about pay, a story bank, the day before and the day itself, and a thank you note), 20 SQL questions with possible answers and lined space for notes, and a checklist for the night before. The two questions on this page are free to use now.
Not getting interviews yet? Our software and IT resumé help shows what hiring managers screen for first.
More roles: interview questions by role.
Don't see your job? Tell us.
Tell us the job you're interviewing for, and we'll write interview questions and model answers for it. It's free to ask. We read every request. We can't promise to add every role, but the most requested ones go first.
Thanks. We got your request.