CMD Guide
HomeDatabasesSQL Practice Problems

Students Report By Geography

This pivot works because a synthetic per-continent rank (rn) becomes a join key across columns: students that share an rn are forced onto the same output row, and within that single-rn group each column's CASE emits one real name plus NULLs, which MAX silently discards because aggregate functions skip NULLs.

The problem

The Student table is a tall, two-column list: (name, continent), possibly with duplicate rows. A school draws students from Asia, Europe, and America. We must pivot it into three columns — America, Asia, Europe — with each continent's names sorted alphabetically and stacked under its header. Where a continent runs out of students, the cell is NULL. This is LeetCode 618.

Student (input)            Desired output
+----------+-----------+   +---------+------+--------+
| name     | continent |   | America | Asia | Europe |
+----------+-----------+   +---------+------+--------+
| Jane     | America   |   | Jack    | Xi   | Pascal |
| Pascal   | Europe    |   | Jane    | NULL | NULL   |
| Xi       | Asia      |   +---------+------+--------+
| Jack     | America   |
+----------+-----------+

The core difficulty: rows have no natural alignment

Pivoting in SQL means turning row values (continent names) into columns. A plain GROUP BY continent can't do it: that produces one row per continent (three rows), but the spec wants America's names stacked vertically next to Asia's and Europe's. There is no column in the source that says "Jack and Xi and Pascal all belong on output line 1." Jack (America) and Xi (Asia) have nothing in common — different names, different continents.

So we manufacture the missing alignment key. Number each continent's students independently, alphabetically: America gets Jack=1, Jane=2; Asia gets Xi=1; Europe gets Pascal=1. That number, rn, is the load-bearing trick — it says "the 1st American, the 1st Asian, and the 1st European share output row 1." Without rn there is nothing to GROUP BY that lines the columns up.

Step 1 — manufacture the alignment key with ROW_NUMBER

ROW_NUMBER() is a window function: it numbers rows within each partition in a specified order, restarting the count at every partition boundary.

SELECT continent,
       name,
       ROW_NUMBER() OVER (
         PARTITION BY continent   -- restart counting per continent
         ORDER BY name            -- alphabetical within the continent
       ) AS rn
FROM Student;

PARTITION BY continent splits the rows into one bucket per continent; ORDER BY name sorts inside each bucket; ROW_NUMBER() stamps 1, 2, 3, … per bucket. After Step 1:

+-----------+--------+----+
| continent | name   | rn |
+-----------+--------+----+
| America   | Jack   |  1 |   <- 1st American
| America   | Jane   |  2 |   <- 2nd American
| Asia      | Xi     |  1 |   <- 1st Asian
| Europe    | Pascal |  1 |   <- 1st European
+-----------+--------+----+

Now rows that belong on the same output line carry the same rn. The alignment problem is solved; the rest is collapsing.

Step 2 — collapse each rn-group with MAX(CASE …)

Group the Step-1 result by rn and, for each continent, pull the name with a conditional aggregate. This is the part the mechanism sentence is really about, so trace it carefully.

SELECT MAX(CASE WHEN continent = 'America' THEN name END) AS America,
       MAX(CASE WHEN continent = 'Asia'    THEN name END) AS Asia,
       MAX(CASE WHEN continent = 'Europe'  THEN name END) AS Europe
FROM (
  SELECT continent, name,
         ROW_NUMBER() OVER (PARTITION BY continent ORDER BY name) AS rn
  FROM Student
) t
GROUP BY rn
ORDER BY rn;

Why MAX over the CASE actually works (the deep part)

Take the group rn = 1. After Step 1 it contains exactly three rows — Jack/America, Xi/Asia, Pascal/Europe — and we feed all three into each of the three aggregate columns. Watch the America column. Its CASE WHEN continent = 'America' THEN name END has no ELSE, so any row whose continent isn't America falls through to an implicit ELSE NULL:

row fed to the America column (rn=1)CASE result
Jack / America'Jack'
Xi / AsiaNULL (no ELSE)
Pascal / EuropeNULL (no ELSE)

So the America column inside group rn=1 sees the multiset {'Jack', NULL, NULL}. Now the two facts that make the trick collapse cleanly:

  1. Aggregate functions ignore NULL. The SQL standard says MAX (and MIN, SUM, AVG, COUNT(col)) discard NULL inputs before aggregating. So MAX({'Jack', NULL, NULL}) = MAX({'Jack'}) = 'Jack'.
  2. At most one non-NULL can ever exist per group. Within one continent, rn is unique (ROW_NUMBER never repeats a number in a partition). So among the three rows sharing rn=1, exactly one is American — meaning the America column's CASE yields exactly one real name and the rest NULL. MAX of "one value and some NULLs" is just that one value.

That second fact is why the choice of aggregate is irrelevant: MAX, MIN, or even SUM (for numbers) would all return the same answer, because there is never more than one non-NULL to choose between. MAX is not picking the alphabetically-largest name — there is only ever one candidate. The aggregate's real job is purely to collapse three rows into one while the NULL-skipping rule lets the lone real value survive in each column.

For the group rn=2 the multiset for America is {'Jane'} (only Jane has rn=2), and for Asia and Europe it is {NULL} — there is no 2nd Asian or European. MAX({NULL}) is NULL, which is exactly the empty cell the spec wants. After Step 2, ordered by rn:

+---------+------+--------+
| America | Asia | Europe |
+---------+------+--------+
| Jack    | Xi   | Pascal |   <- rn = 1
| Jane    | NULL | NULL   |   <- rn = 2
+---------+------+--------+
diagram
diagram

Why the naive attempts are wrong

Plain GROUP BY continent. SELECT MAX(name) FROM Student GROUP BY continent gives one row per continent and only the alphabetically-last name — you lose every other student and never get the vertical stacking. There is no rn, so nothing aligns columns.

Self-joins. Joining three filtered copies of Student on a shared row index also works in principle, but you must still synthesize that row index with ROW_NUMBER, and you need a FULL OUTER JOIN to keep continents of unequal length — more code, more NULL bookkeeping, same idea underneath. The MAX(CASE) pivot is the compact form.

Pitfalls

Takeaways


Problem from LeetCode 618 "Students Report By Geography." NULL-handling of aggregate functions per the SQL standard (ISO/IEC 9075) and the PostgreSQL and MySQL manuals ("Aggregate functions … ignore NULL values"). ROW_NUMBER window-function semantics per the PostgreSQL window-functions documentation. Re-authored and deepened for this guide to explain the load-bearing rn-alignment idea and, in full, why MAX over the CASE collapses each group to a single non-NULL value.

🤖 Don't fully get this? Learn it with Claude

Stuck on Students Report By Geography? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Students Report By Geography** (Databases) and want to truly understand it. Explain Students Report By Geography 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.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Students Report By Geography** 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.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Students Report By Geography** 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.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Students Report By Geography** 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.

📝 My notes