Expert: design, speed and engines · Interview questions and practice projects · topic 58 of 62 · 40 min
Classic interview queries, part 1
Explanation
Why these questions?
Interviewers reuse a small set of questions because each one tests a core skill in a few lines: subqueries, GROUP BY with HAVING, self joins, outer joins and window functions. They care less about the exact answer and more about whether you notice the traps: ties, NULLs and duplicates. Practise saying your thinking out loud while you write.
Second highest salary, three ways
Salaries in COMPANY are monthly. The highest is 250000 and the second highest distinct salary is 120000. "Distinct" matters: if two people shared the top salary, the second highest is still the next different value.
-- 1. MAX below the MAX (works everywhere)
SELECT MAX(salary) AS second_highest
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees); -- 120000
-- 2. DISTINCT + LIMIT/OFFSET (SQLite, PostgreSQL, MySQL)
SELECT DISTINCT salary FROM employees
ORDER BY salary DESC LIMIT 1 OFFSET 1; -- 120000
-- 3. DENSE_RANK (also gives names, handles ties)
SELECT name, salary
FROM (SELECT name, salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS dr
FROM employees) AS ranked
WHERE dr = 2; -- Rahul Sharma | 120000Without DISTINCT, way 2 is wrong when the top salary repeats: it would return the top salary again. Way 1 returns NULL when there is no second value, which interviewers often want ("return NULL if there is none"). Way 2 returns no row in that case.
Nth highest
For the Nth highest, use OFFSET N − 1 with DISTINCT, or DENSE_RANK() = N. DENSE_RANK gives tied salaries the same rank and leaves no gaps, so dr = 5 returns both Anita Desai and Vikram Singh (95000). RANK would leave a gap after a tie, and ROW_NUMBER would pick one of them at random, so they answer different questions.
Finding duplicates
Duplicates are rows that should be unique but are not, such as the same email signed up twice. Group by the column that should be unique and keep groups with more than one row.
SELECT email, COUNT(*) AS cnt
FROM signups
GROUP BY email
HAVING COUNT(*) > 1;
-- asha@example.com | 3
-- ravi@example.com | 2Deleting duplicates but keeping one
DELETE FROM signups
WHERE id NOT IN (SELECT MIN(id) FROM signups GROUP BY email);
-- keeps ids 1, 2, 4, 6: the first sign-up for each emailAnother common answer uses ROW_NUMBER() OVER (PARTITION BY email ORDER BY id) and deletes rows numbered above 1. Afterwards, add a UNIQUE constraint so duplicates cannot come back.
Employees who earn more than their manager
This is a self join: the employees table joined to itself, once as the employee (e) and once as the manager (m). In COMPANY nobody out-earns their manager, so the query correctly returns no rows. On a small staff table it finds two people:
SELECT e.name AS employee, e.salary, m.name AS manager, m.salary AS manager_salary
FROM staff e
JOIN staff m ON m.id = e.manager_id
WHERE e.salary > m.salary;
-- Nisha | 98000 | Joseph | 90000
-- Tara | 160000 | Kiran | 150000Top earner per department
SELECT d.name AS department, e.name, e.salary
FROM employees e
JOIN departments d ON d.id = e.dept_id
WHERE e.salary = (SELECT MAX(salary) FROM employees x WHERE x.dept_id = e.dept_id);
-- Engineering | Meera Iyer | 250000
-- Sales | Pooja Gupta | 110000
-- Finance | Farhan Ali | 105000
-- HR | Lakshmi Pillai | 80000Departments with no employees
SELECT d.name
FROM departments d
LEFT JOIN employees e ON e.dept_id = d.id
WHERE e.id IS NULL; -- LegalCommon mistakes
- Forgetting DISTINCT in the LIMIT/OFFSET answer, so a repeated top salary breaks it.
- Using ROW_NUMBER when the question needs ties kept. Use DENSE_RANK (or RANK) and say why.
- Writing WHERE COUNT(*) > 1. Aggregates go in HAVING.
- Deleting duplicates without checking first. Run the SELECT version, use a transaction, then add a UNIQUE constraint.
- Using NOT IN with a subquery that returns NULL, which makes the whole result empty. Use NOT EXISTS or LEFT JOIN ... IS NULL.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Classic interview queries, part 1 · 1/8
Some SQL questions come up in nearly every interview. Let us learn them, with more than one answer each.
Prefer a video by a teacher? Find free videos on “sql interview questions second highest salary duplicates self join” on YouTube ↗
In real life: Cleaning duplicate customers before a campaign
Before sending an offer by SMS, a retail chain's analyst checks how many phone numbers appear more than once in the customer table (people often sign up again at a new store). The GROUP BY ... HAVING query sizes the problem, a ROW_NUMBER query picks the record to keep, and after a careful delete a UNIQUE constraint stops it from happening again. The same three steps appear in many data-cleaning jobs.
SELECT email, COUNT(*) AS cnt
FROM signups
GROUP BY email
HAVING COUNT(*) > 1
ORDER BY cnt DESC;Practice (0/4 done)
Find the second highest distinct salary in employees (COMPANY). Return one column named second_highest.
Use DENSE_RANK to find everyone with the 3rd highest distinct salary. Return name and salary.
The signups table has repeated emails. Return email and cnt (the number of rows with that email) for every email that appears more than once.
For each department, return the highest-paid employee: department (the department name), name and salary. If two people tied, both should appear. Employees with no department are left out.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Classic interview queries, part 2Interview questions and practice projects · same module
- Theory questions you will be askedInterview questions and practice projects · same module
- Project: a railway booking database (IRCTC-like)Interview questions and practice projects · same module
- Self joins and cross joinsJOINs
- Ranking: ROW_NUMBER, RANK, DENSE_RANK and NTILEWindow functions
- GROUP BYAggregation: GROUP BY and HAVING
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
Salaries are 100, 100, 90, 80. What does SELECT salary FROM t ORDER BY salary DESC LIMIT 1 OFFSET 1 return?
Answer: 100
Without DISTINCT the second row is the second 100. Add DISTINCT to get 90.
Two employees tie for the 2nd highest salary. Which function returns both of them for "rank = 2"?
Answer: DENSE_RANK
DENSE_RANK (and RANK) give ties the same rank; ROW_NUMBER numbers them 2 and 3.
Why must the duplicates filter be HAVING COUNT(*) > 1 and not WHERE COUNT(*) > 1?
Answer: WHERE runs before grouping, so counts do not exist yet
WHERE filters rows before GROUP BY; HAVING filters groups after the counts are made.
Which query pattern finds departments that have no employees?
Answer: departments LEFT JOIN employees, keeping rows where the employee id IS NULL
A LEFT JOIN keeps every department; those with no match have NULLs on the employee side.
Which join answers "employees who earn more than their manager"?
Answer: A self join: employees e JOIN employees m ON m.id = e.manager_id
Both people are in the same table, so you join the table to itself with two aliases.
You need the top 3 salaries per department, and everyone tied with the 3rd must be included. Which do you use?Related
Answer: RANK() and rnk <= 3
RANK keeps all tied rows; ROW_NUMBER picks only one of them.
employees has 11 rows. How many rows does SELECT name, AVG(salary) OVER (PARTITION BY dept_id) FROM employees return?Related
Answer: 11
A window function never removes rows; each of the 11 rows gets its department average.
The query "employees who earn more than their manager" returns no rows on COMPANY. What should you do first?Related
Answer: Look at the data: if every manager earns more, an empty result is correct
An empty result can be the right answer. Check before changing the query.
Salaries in order are 300, 200, 200, 100. What does RANK() OVER (ORDER BY salary DESC) give?Related
Answer: 1, 2, 2, 4
RANK gives ties the same number and then skips, so the next rank is 4.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 4 more topics in “Interview questions and practice projects” before its exam: Classic interview queries, part 2, Theory questions you will be asked, Project: a railway booking database (IRCTC-like), Project: e-commerce analytics, and your next steps.
- Module 12 exam: interview questions and projects · 13 questions · 25 min, without help. 5 topics of this module still to finish first.
- 62 topics left in the course before the final exam.