Biểu đồ của bạn nhìn rất mượt. Vì những tháng không có doanh thu đã lặng lẽ biến mất khỏi trục.
Bài toán
Báo cáo “mỗi sinh viên làm bao nhiêu bài ở mỗi môn”. Nếu An chưa làm bài Lý nào, dòng đó không tồn tại trong bảng dữ liệu — nên nó biến mất khỏi báo cáo thay vì hiện số 0.
Cách đúng: tạo khung trước, ghép sau
SELECT
sv.ten,
mh.ten AS mon,
COUNT(bt.id) AS so_bai
FROM sinh_vien sv
CROSS JOIN mon_hoc mh
LEFT JOIN bai_thi bt
ON bt.sinh_vien_id = sv.id
AND bt.mon_hoc_id = mh.id
GROUP BY sv.ten, mh.ten
ORDER BY sv.ten, mh.ten;
Ba bước: CROSS JOIN tạo đủ mọi ô của bảng kết quả → LEFT JOIN đổ dữ liệu vào ô nào có → COUNT trả về 0 cho ô rỗng.
COUNT(*) đếm cả dòng do LEFT JOIN sinh ra, nên ô rỗng sẽ ra 1 thay vì 0. COUNT(cột) bỏ qua NULL nên ra đúng 0.
Lỗi thường gặp
1. Quên điều kiện ghép — nổ số dòng
-- 10.000 × 5.000 = 50 triệu dòng
SELECT * FROM khach_hang, don_hang;
Dấu phẩy giữa hai bảng chính là CROSS JOIN. Đây là cách phổ biến nhất để treo máy chủ mà không hề cố ý.
2. Dùng CROSS JOIN khi thật ra cần INNER JOIN
CROSS JOIN chỉ đúng khi bạn muốn mọi tổ hợp. Với dữ liệu có quan hệ, luôn ghi rõ ON.
Ứng dụng thứ hai: tạo dải ngày liên tục
WITH cac_ngay AS (
SELECT generate_series('2026-01-01'::date,
'2026-01-31'::date, '1 day') AS ngay
)
SELECT n.ngay, COALESCE(SUM(d.tong_tien), 0) AS doanh_thu
FROM cac_ngay n
LEFT JOIN don_hang d ON d.ngay_dat::date = n.ngay
GROUP BY n.ngay
ORDER BY n.ngay;
Mọi ngày đều xuất hiện, ngày không bán được hiện 0. Đây cũng chính là lý do trong Power BI bạn phải tạo bảng lịch riêng.
Luyện tập
- LeetCode 1280 — Students and Examinations
- LeetCode 1789 — Primary Department for Each Employee
- LeetCode 1350 — Students With Invalid Departments
- HackerRank — Draw The Triangle 1 và 2
Tóm lại
CROSS JOINtạo mọi tổ hợp giữa hai bảng.- Dùng để tạo khung báo cáo đầy đủ trước khi đổ dữ liệu vào.
- Dùng
COUNT(cột), không dùngCOUNT(*), để ô rỗng ra 0. - Dấu phẩy giữa hai bảng chính là
CROSS JOIN— nguồn gốc của mọi vụ nổ số dòng. - Cùng kỹ thuật này dùng để tạo dải ngày liên tục.
Bạn vừa học xong CROSS JOIN
Sẵn sàng luyện tập chưa?
Làm bài tập CROSS JOIN 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 →