Bạn gõ UNION theo thói quen. Nó âm thầm sắp xếp lại 8 triệu dòng để khử trùng lặp không hề tồn tại.
Bài toán
Ghép danh sách khách từ hai bảng (khách cũ và khách mới) thành một danh sách duy nhất.
Khác biệt duy nhất cần nhớ
UNION | UNION ALL | |
|---|---|---|
| Bản trùng | Bị loại | Giữ nguyên |
| Chi phí | Phải sắp xếp toàn bộ | Chỉ nối vào nhau |
| Tốc độ | Chậm hơn nhiều | Nhanh |
UNION phải sắp xếp hoặc băm toàn bộ kết quả để biết dòng nào trùng. Trên 8 triệu dòng, đó là vài giây so với vài phần trăm giây.
UNION ALL, trừ khi bạn biết chắc có bản trùng và thật sự cần loại chúng đi.
Lỗi thường gặp
1. Số cột không khớp
-- Lỗi
SELECT ten, email FROM khach_cu
UNION ALL
SELECT ten FROM khach_moi;
Hai vế phải có cùng số cột và cùng kiểu dữ liệu theo thứ tự. Thiếu cột thì bù bằng hằng số:
SELECT ten, NULL AS email FROM khach_moi;
2. Tên cột lấy từ vế đầu tiên
Vế thứ hai đặt bí danh gì cũng vô nghĩa. Muốn đổi tên cột, sửa ở vế đầu.
3. ORDER BY đặt sai chỗ
-- Chỉ sắp xếp vế đầu, hoặc báo lỗi tuỳ hệ
SELECT ten FROM khach_cu ORDER BY ten
UNION ALL
SELECT ten FROM khach_moi;
-- Đúng: ORDER BY áp cho toàn bộ, đặt ở cuối
SELECT ten FROM khach_cu
UNION ALL
SELECT ten FROM khach_moi
ORDER BY ten;
4. Dùng UNION để thay LEFT JOIN
Nếu bạn đang UNION hai truy vấn gần giống nhau chỉ khác điều kiện, thường có một câu CASE WHEN hoặc LEFT JOIN gọn hơn và nhanh hơn nhiều.
Hai họ hàng ít dùng nhưng hữu ích
-- Dòng có ở cả hai
SELECT id FROM bang_a INTERSECT SELECT id FROM bang_b;
-- Dòng có ở A mà không có ở B
SELECT id FROM bang_a EXCEPT SELECT id FROM bang_b;
EXCEPT (MySQL gọi là MINUS ở Oracle) là cách viết anti-join ngắn nhất khi chỉ cần so một cột.
Luyện tập
- LeetCode 1965 — Employees With Missing Information
- LeetCode 1581 — Customer Who Visited but Did Not Make Any Transactions
- LeetCode 1741 — Find Total Time Spent by Each Employee
- HackerRank — The Report
Tóm lại
UNIONkhử trùng lặp và phải sắp xếp toàn bộ;UNION ALLchỉ nối.- Mặc định dùng
UNION ALL. - Hai vế phải khớp số cột và kiểu dữ liệu.
- Tên cột lấy từ vế đầu tiên.
ORDER BYđặt ở cuối cùng, áp cho toàn bộ kết quả.
Bạn vừa học xong UNION và UNION ALL
Sẵn sàng luyện tập chưa?
Làm bài tập UNION và UNION ALL 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 →