Find the Quiet Students in All Exams
Mechanism
Rank every student twice inside each exam — once descending (so rank 1 is the top score) and once ascending (so rank 1 is the bottom score) — then any student who ever earns a rank 1 in either direction in any exam is loud; the quiet students are exactly those who took an exam but appear in neither rank-1 set.
The whole trick is that "highest in this exam" and "lowest in this exam" are both just "rank 1" under opposite sort orders. Compute both with two windowed RANK()s over the same PARTITION BY exam_id, collapse every loud student into one exclusion list, and subtract that list from everyone who sat an exam.
Problem
Table Student(student_id PK, student_name); table Exam(exam_id, student_id, score) with composite PK (exam_id, student_id) — one row per student per exam.
A quiet student took at least one exam and never scored the highest or the lowest in any exam they sat. Report (student_id, student_name) for the quiet students, ordered by student_id. Never return a student who took no exam.
The data we will trace
Everything below is computed from this input — every rank and every verdict traces back to a real score here, nothing is fabricated.
Student
| student_id | student_name |
|---|---|
| 1 | Daniel |
| 2 | Jade |
| 3 | Stella |
| 4 | Jonathan |
| 5 | Will |
Exam — note Will (5) never appears, so he must not be in the answer; exam 20 has a single taker.
| exam_id | student_id | score |
|---|---|---|
| 10 | 1 | 90 |
| 10 | 2 | 80 |
| 10 | 3 | 70 |
| 20 | 1 | 95 |
| 30 | 1 | 60 |
| 30 | 3 | 80 |
| 30 | 4 | 90 |
| 40 | 1 | 50 |
| 40 | 2 | 70 |
| 40 | 4 | 100 |
The query
WITH ranked AS (
SELECT exam_id,
student_id,
RANK() OVER (PARTITION BY exam_id ORDER BY score DESC) AS high_rank,
RANK() OVER (PARTITION BY exam_id ORDER BY score ASC) AS low_rank
FROM Exam
)
SELECT DISTINCT s.student_id, s.student_name
FROM Student s
JOIN Exam e ON e.student_id = s.student_id -- only students who sat an exam
WHERE s.student_id NOT IN (
SELECT student_id
FROM ranked
WHERE high_rank = 1 OR low_rank = 1 -- ever top OR ever bottom
)
ORDER BY s.student_id;The inner JOIN on Exam is what enforces "took at least one exam" — Will (5) has no Exam row, so he is dropped before the filter even runs. The NOT IN then removes every loud student.
Step 1 — rank within each exam (the ranked CTE)
Each row's two ranks are computed only from the scores in that exam. Read a row as: "in exam 10, Daniel's 90 is the highest (high_rank 1) and the 3rd-lowest (low_rank 3)."
| exam_id | student_id | score | high_rank | low_rank |
|---|---|---|---|---|
| 10 | 1 | 90 | 1 | 3 |
| 10 | 2 | 80 | 2 | 2 |
| 10 | 3 | 70 | 3 | 1 |
| 20 | 1 | 95 | 1 | 1 |
| 30 | 1 | 60 | 3 | 1 |
| 30 | 3 | 80 | 2 | 2 |
| 30 | 4 | 90 | 1 | 3 |
| 40 | 1 | 50 | 3 | 1 |
| 40 | 2 | 70 | 2 | 2 |
| 40 | 4 | 100 | 1 | 3 |
Exam 20 is the instructive edge: with one taker, that 95 is simultaneously the highest and the lowest, so Daniel gets high_rank = low_rank = 1. A sole taker is always loud.
Step 2 — collect the loud students
Keep every ranked row where high_rank = 1 OR low_rank = 1, take the DISTINCT student_ids. Walking the table above:
- Daniel (1): high_rank 1 in exam 10, both ranks 1 in exam 20, low_rank 1 in exams 30 and 40 — loud many times over.
- Stella (3): low_rank 1 in exam 10 — loud.
- Jonathan (4): high_rank 1 in exams 30 and 40 — loud.
- Jade (2): ranks 2/2 in exam 10 and 2/2 in exam 40 — never appears here.
excluded student_id
-------------------
1 (Daniel)
3 (Stella)
4 (Jonathan)Step 3 — subtract, then the final answer
Everyone who sat an exam is {1, 2, 3, 4}. Remove the loud set {1, 3, 4} and only Jade survives. Joining back to Student for her name:
+------------+--------------+
| student_id | student_name |
+------------+--------------+
| 2 | Jade |
+------------+--------------+This checks out against the raw scores: Jade got 80 in exam 10 (between Daniel's 90 and Stella's 70) and 70 in exam 40 (between Jonathan's 100 and Daniel's 50) — middle both times. Will (5) is correctly absent because he has no Exam row at all.
Pitfalls
ROW_NUMBER()instead ofRANK()silently breaks on ties. Suppose two students tie for the top score in an exam.RANK()gives both rank 1, so both are flagged loud.ROW_NUMBER()hands out 1 and 2 arbitrarily — the second top-scorer gets rank 2 and survives as "quiet" even though they tied for highest.DENSE_RANK()works too; the rule is: use a function that gives tied extremes the same rank.NOT INis NULL-poisoned. If the subquery afterNOT INever yields aNULL, the whole predicate evaluates toUNKNOWNfor every row and you get zero results. Here it is safe only becausestudent_idis part ofExam's primary key and is never NULL. Make that an explicit habit — when in doubt, writeNOT EXISTS (SELECT 1 FROM excluded x WHERE x.student_id = e.student_id), which is NULL-safe by construction, or addWHERE student_id IS NOT NULLto the subquery.- Forgetting the "took an exam" guard. If you build the result from
Student LEFT JOIN Examor drive offStudentalone, a student with no exams (Will) passes theNOT INfilter — he was never loud — and wrongly lands in the output. Drive the final query offExam(or inner-join it) so non-takers are excluded structurally. - Single-taker exams are a trap, not an exception. One student in an exam is both the max and the min, so that exam can never produce a quiet survivor — it always flags its lone taker loud. That is correct behavior, but it surprises people who assume "middle" requires three rows.
Takeaways
- "Highest" and "lowest" are the same operation under opposite sort orders — two
RANK()s over one partition, both checked for rank 1. - The exclusion model (collect the loud set once, subtract it) is cleaner and faster than per-exam anti-joins or correlated
MAX/MINcomparisons. - Use
RANK()/DENSE_RANK(), notROW_NUMBER(), whenever ties at an extreme must all count. - Reach for
NOT EXISTSoverNOT INunless you can prove the subquery is NULL-free.
Problem from LeetCode 1412 "Find the Quiet Students in All Exams". SQL window-function semantics per the PostgreSQL documentation (window functions, RANK/ROW_NUMBER/DENSE_RANK) and the SQL:2003 windowing standard; the NOT IN NULL behavior follows the SQL three-valued-logic rules also documented by PostgreSQL and Oracle. Worked dataset re-authored from scratch so every rank and the final answer trace back to a shown input table, and the RANK-vs-ROW_NUMBER and NULL-safe-NOT IN pitfalls added. Re-authored / deepened for this guide.
🤖 Don't fully get this? Learn it with Claude
Stuck on Find the Quiet Students in All Exams? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Build the mental picture, not memorization.
I just read a lesson on **Find the Quiet Students in All Exams** (Databases) and want to truly understand it. Explain Find the Quiet Students in All Exams from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Socratic — adapts to where you're stuck.
Teach me **Find the Quiet Students in All Exams** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Active recall exposes what you missed.
Quiz me on **Find the Quiet Students in All Exams** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Intuition + hook + flashcards for long-term memory.
Help me remember **Find the Quiet Students in All Exams** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.