Khi gộp dữ liệu từ hai truy vấn, một từ ALL có thể thay đổi số dòng kết quả. Nếu mỗi dòng đại diện cho một sự kiện, loại trùng ngoài ý muốn có thể làm báo cáo thiếu dữ liệu. Ngược lại, giữ mọi dòng có thể không đúng khi yêu cầu là danh sách giá trị duy nhất.
1. Chọn theo ý nghĩa dữ liệu
Theo tài liệu PostgreSQL về kết hợp truy vấn, UNION loại các dòng trùng khỏi kết quả, còn UNION ALL giữ chúng. Hai nhánh phải trả cùng số cột với kiểu dữ liệu tương thích ở các vị trí tương ứng.
Đừng hiểu UNION là “gộp theo khóa chính”. Nó xét các cột được chọn trong kết quả. Nếu bạn chỉ chọn tên, hai người khác nhau cùng tên có thể bị gộp thành một giá trị.
2. Ví dụ chỉ đọc, không cần tạo bảng
Các truy vấn minh họa sau dùng VALUES trên PostgreSQL. Truy vấn đầu có kết quả mong đợi là ba giá trị 1, 2, 3:
SELECT customer_id
FROM (VALUES (1), (2)) AS a(customer_id)
UNION
SELECT customer_id
FROM (VALUES (2), (3)) AS b(customer_id)
ORDER BY customer_id;
Đổi sang UNION ALL, giá trị 2 được giữ hai lần và kết quả mong đợi có bốn dòng:
SELECT customer_id
FROM (VALUES (1), (2)) AS a(customer_id)
UNION ALL
SELECT customer_id
FROM (VALUES (2), (3)) AS b(customer_id)
ORDER BY customer_id;
Không có thao tác ghi dữ liệu trong hai ví dụ. Tuy vậy, khi áp dụng lên bảng thật, vẫn nên chạy trong môi trường kiểm thử và xem xét tải truy vấn.
3. Thêm cột nguồn sẽ thay đổi định nghĩa dòng trùng
SELECT 2 AS customer_id, 'website' AS source
UNION
SELECT 2 AS customer_id, 'store' AS source;
Kết quả có hai dòng vì source khác nhau. Nếu nghiệp vụ cần một khách hàng duy nhất bất kể nguồn, phải xác định cách tổng hợp hoặc chọn nguồn, không thể chỉ thêm UNION rồi kỳ vọng hệ quản trị tự hiểu ý nghĩa khách hàng.
Trong báo cáo sự kiện, hai dòng có cùng người dùng và cùng loại hành động vẫn có thể là hai lần thực hiện hợp lệ. Giữ mã sự kiện hoặc những trường nhận diện cần thiết sẽ giúp tránh đánh đồng “giá trị giống nhau” với “cùng một sự kiện”.
4. Gộp dữ liệu không bảo đảm thứ tự
Hướng dẫn ORDER BY của PostgreSQL nhấn mạnh rằng không có sắp xếp tường minh thì thứ tự không được bảo đảm. Không dựa vào việc truy vấn thử nghiệm luôn in nhánh đầu trước nhánh sau.
Đặt ORDER BY cho toàn bộ kết quả như hai ví dụ trên. Nếu nhiều dòng có cùng giá trị sắp xếp nhưng ứng dụng cần thứ tự xác định giữa chúng, bổ sung khóa phân xử phù hợp. Với dữ liệu nhiều nguồn, mã bản ghi chỉ duy nhất trong từng nguồn có thể chưa đủ; cần xét cả nguồn.
Khi cần LIMIT hoặc ORDER BY riêng từng nhánh, dùng dấu ngoặc để thể hiện phạm vi rõ ràng. Giới hạn trên từng nguồn và giới hạn trên kết quả đã gộp trả lời hai câu hỏi khác nhau; không chuyển vị trí LIMIT chỉ để truy vấn chạy nhanh hơn.
5. Hiệu năng là bước sau tính đúng
Loại trùng có thể phát sinh công việc xử lý thêm, nhưng không có bảo đảm rằng đổi UNION thành UNION ALL luôn cải thiện thời gian theo một tỷ lệ cố định. Quan trọng hơn, đổi cú pháp có thể đổi kết quả.
Hãy ghi rõ yêu cầu giữ hay loại các lần xuất hiện, kiểm tra kết quả với dữ liệu đại diện rồi mới xem kế hoạch thực thi. Đừng sửa truy vấn báo cáo bằng cách tối ưu trước và kiểm tra tổng số sau.
6. Checklist kiểm thử
- Hai nguồn không có dòng giống nhau.
- Có dòng giống nhau giữa hai nguồn và có dòng lặp ngay trong một nguồn.
- Một nguồn rỗng hoặc cả hai nguồn đều rỗng.
- Thêm một cột mới có làm thay đổi việc loại trùng không?
- Các cột cùng vị trí có cùng ý nghĩa nghiệp vụ, không chỉ tương thích kiểu dữ liệu?
- Thứ tự và giới hạn kết quả có đúng yêu cầu màn hình hoặc báo cáo?
Nguyên tắc ngắn gọn: dùng UNION ALL khi cần giữ mọi lần xuất hiện, dùng UNION khi thực sự cần loại các dòng kết quả trùng nhau. Trước khi gộp, hãy xác định một dòng đang đại diện cho khách hàng, sự kiện hay một giá trị thống kê.




Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.