Pivoting in SQL: Turning Rows Into Columns With CASE

Intermediate 5 min read Updated 30 Jul 2026 UPA AI Partner

Your manager wants a wide report; the data is tall. Skip the Excel export — four lines of SQL will do it.

The problem

Scores are stored tall: one row per subject. The report needs them wide: one column per subject.

DẠNG DỌCtenmondiemAnToán9An7BìnhToán6Bình8DẠNG NGANGtenToánAn97Bình68CASE + MAX

The pivot formula

SELECT
  name,
  MAX(CASE WHEN subject = 'Maths'   THEN score END) AS maths,
  MAX(CASE WHEN subject = 'Physics' THEN score END) AS physics,
  MAX(CASE WHEN subject = 'Chem'    THEN score END) AS chem
FROM scores
GROUP BY name;

Three fixed parts:

  1. GROUP BY the column that becomes the rows of the output
  2. CASE WHEN picks the value belonging to each column
  3. MAX or SUM collapses the group into a single row

Common mistakes

1. Forgetting the aggregate

-- Returns 4 rows, each with only one populated cell
SELECT name,
  CASE WHEN subject = 'Maths'   THEN score END AS maths,
  CASE WHEN subject = 'Physics' THEN score END AS physics
FROM scores;

CASE evaluates row by row, so it cannot collapse anything on its own. Wrap it in MAX and add GROUP BY.

2. Using MAX where SUM was meant

MAX is right when each cell holds one value. If a student sat Maths twice, MAX returns only the higher score — which may or may not be what you want. Use SUM to total them.

3. Adding ELSE 0 where it does not belong

-- A student who never sat Chemistry shows 0 rather than blank
MAX(CASE WHEN subject = 'Chem' THEN score ELSE 0 END)

For counts, ELSE 0 is correct. For values, leaving NULL is honest — scoring zero and not sitting the exam are different facts.

Unpivoting: columns back into rows

SELECT name, 'Maths'   AS subject, maths   AS score FROM wide_scores
UNION ALL
SELECT name, 'Physics', physics FROM wide_scores
UNION ALL
SELECT name, 'Chem',    chem    FROM wide_scores;

This is LeetCode 1795 — a shape that comes up constantly in analytics interviews.

The limitation to know SQL cannot invent columns. You must know the list of subjects in advance and type them out. Dynamic column counts require generating the statement from an application.

Practice

  • LeetCode 1179 — Reformat Department Table
  • LeetCode 1795 — Rearrange Products Table
  • LeetCode 1873 — Calculate Special Bonus
  • HackerRank — Occupations (a hard pivot, worth doing)

Key takeaways

  • A pivot is GROUP BY + CASE WHEN + an aggregate.
  • Without MAX/SUM you get scattered rows.
  • MAX for one value per cell, SUM when totalling.
  • ELSE 0 is right for counts, wrong for values.
  • Unpivot with UNION ALL.

You have just learned xoay bảng bằng CASE

Ready to practise?

Work through xoay bảng bằng CASE exercises on real data, graded the moment you hit run.

Start practising →