Sếp muốn báo cáo ngang, dữ liệu lại nằm dọc. Đừng xuất Excel — bốn dòng SQL là xong.
Bài toán
Bảng điểm lưu dạng dọc: mỗi dòng là một môn. Báo cáo cần dạng ngang: mỗi môn là một cột.
Công thức pivot
SELECT
ten,
MAX(CASE WHEN mon = 'Toán' THEN diem END) AS toan,
MAX(CASE WHEN mon = 'Lý' THEN diem END) AS ly,
MAX(CASE WHEN mon = 'Hoá' THEN diem END) AS hoa
FROM bang_diem
GROUP BY ten;
Ba thành phần cố định:
GROUP BYcột sẽ thành dòng của bảng kết quảCASE WHENchọn ra giá trị thuộc cột đóMAXhoặcSUMnén nhóm lại thành một dòng
Lỗi thường gặp
1. Quên hàm tổng hợp
-- Ra 4 dòng, mỗi dòng chỉ có 1 ô có giá trị
SELECT ten,
CASE WHEN mon = 'Toán' THEN diem END AS toan,
CASE WHEN mon = 'Lý' THEN diem END AS ly
FROM bang_diem;
CASE chạy theo từng dòng nên không tự gom được. Phải bọc MAX và thêm GROUP BY.
2. Dùng MAX khi cần SUM
MAX đúng khi mỗi ô chỉ có một giá trị. Nếu một học sinh thi Toán hai lần, MAX chỉ lấy điểm cao hơn — có thể đúng ý, có thể không. Muốn cộng lại thì dùng SUM.
3. Thêm ELSE 0 vào chỗ không nên
-- Học sinh chưa thi Hoá sẽ hiện 0 thay vì để trống
MAX(CASE WHEN mon = 'Hoá' THEN diem ELSE 0 END)
Với đếm thì ELSE 0 là đúng. Với giá trị thì để trống (NULL) mới trung thực — 0 điểm và chưa thi là hai chuyện khác nhau.
Pivot ngược: cột thành dòng
SELECT ten, 'Toán' AS mon, toan AS diem FROM bang_ngang
UNION ALL
SELECT ten, 'Lý', ly FROM bang_ngang
UNION ALL
SELECT ten, 'Hoá', hoa FROM bang_ngang;
Đây chính là LeetCode 1795 — dạng bài xuất hiện rất nhiều trong phỏng vấn phân tích dữ liệu.
Luyện tập
- LeetCode 1179 — Reformat Department Table
- LeetCode 1795 — Rearrange Products Table
- LeetCode 1873 — Calculate Special Bonus
- HackerRank — Occupations (pivot khó, đáng làm)
Tóm lại
- Pivot =
GROUP BY+CASE WHEN+ hàm tổng hợp. - Thiếu
MAX/SUMlà ra nhiều dòng rời rạc. MAXcho một giá trị mỗi ô,SUMkhi cần cộng dồn.ELSE 0đúng với đếm, sai với giá trị.- Pivot ngược làm bằng
UNION ALL.
Bạn vừa học xong xoay bảng bằng CASE
Sẵn sàng luyện tập chưa?
Làm bài tập xoay bảng bằng CASE trên dữ liệu thật, chấm điểm ngay khi bạn bấm chạy.
Bắt đầu luyện tập →