Trong MySQL, UNION
mệnh đề kết hợp các kết quả từ nhiều truy vấn thành một tập kết quả duy nhất.
Ví dụ
Giả sử chúng ta có các bảng sau:
SELECT * FROM Teachers;
SELECT * FROM Students;
Kết quả:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | +-----------+-------------+ +-----------+-------------+ | StudentId | StudentName | +-----------+-------------+ | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | | 6 | Bill | +-----------+-------------+
Chúng tôi có thể chèn UNION
mệnh đề giữa hai SELECT
đó câu lệnh gửi lại tất cả giáo viên và học sinh:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentName FROM Students;
Kết quả:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
Tên cột được lấy từ SELECT
đầu tiên tuyên bố.
Theo mặc định, UNION
mệnh đề áp dụng ngầm một DISTINCT
hoạt động. Nói cách khác, nó chỉ trả về các giá trị riêng biệt theo mặc định. Vì vậy, các kết quả trên chỉ chứa một trong số Warren, Cathy và Bill. Điều này là mặc dù thực tế là các bảng kết hợp thực sự chứa hai Warrens, hai Cathys và ba Bills (có hai giáo viên tên là Cathy, một giáo viên và một khách hàng tên là Warren, và hai người tên là Bill, cũng như một học sinh tên là Bill).
Dưới đây là một ví dụ sử dụng rõ ràng DISTINCT
mệnh đề:
SELECT TeacherName FROM Teachers
UNION DISTINCT
SELECT StudentName FROM Students;
Kết quả:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
Vì vậy, chúng tôi nhận được cùng một kết quả mà chúng tôi nhận được mà không có DISTINCT
mệnh đề.
Bao gồm các bản sao
Chúng ta có thể sử dụng ALL
từ khóa để bao gồm các giá trị trùng lặp trong kết quả:
SELECT TeacherName FROM Teachers
UNION ALL
SELECT StudentName FROM Students;
Kết quả:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Cathy | | Bill | | Bill | | Faye | | Jet | | Spike | | Ein | | Warren | | Bill | +-------------+
Lần này chúng ta có 12 hàng thay vì 8 hàng như trong ví dụ đầu tiên.
Chúng ta có thể thấy rằng cả hai Cathys đã được trả lại và cả ba Hóa đơn đã được trả lại.
TABLE
Tuyên bố
Từ MySQL 8.0.19, chúng ta có thể sử dụng UNION
mệnh đề với TABLE
tuyên bố.
Đây là một ví dụ:
TABLE Teachers
UNION
TABLE Students;
Kết quả:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | +-----------+-------------+
Điều đó tương đương với truy vấn sau:
SELECT * FROM Teachers
UNION
SELECT * FROM Students;
Kết quả:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | +-----------+-------------+
Bạn sẽ nhận thấy rằng những câu lệnh này trả về nhiều hàng hơn trong ví dụ đầu tiên của chúng tôi trước đó. Đó là bởi vì chúng tôi đang chọn tất cả các cột trong bảng, điều này dẫn đến các cột không trùng lặp mà trước đó đã có một cột trùng lặp. Ví dụ:hai giáo viên tên là Bill được trả về ở đây trong khi chỉ có một giáo viên được trả lại trong ví dụ trước đó. Đó là vì TeacherId
các cột chứa các giá trị khác nhau, do đó các hàng không trùng lặp.
Sử dụng ORDER BY
Mệnh đề trong Truy vấn Liên minh
Chúng ta có thể sử dụng ORDER BY
mệnh đề trong mỗi SELECT
và / hoặc trên UNION
kết hợp truy vấn.
Trong mỗi SELECT
Tuyên bố
Khi chúng tôi sử dụng ORDER BY
mệnh đề trong SELECT
riêng lẻ các câu lệnh trong UNION
truy vấn, chúng ta cần bao gồm mỗi SELECT
câu lệnh bên trong dấu ngoặc đơn:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2);
Kết quả:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 4 | Ein | +-----------+-------------+
Lưu ý rằng khi chúng tôi làm điều này, nó không thực sự sắp xếp kết quả cho đầu ra. Nó chỉ sắp xếp các kết quả cho mục đích xác định tập hợp con của các hàng đã chọn để truy xuất khi áp dụng LIMIT
mệnh đề.
Do đó, sử dụng ORDER BY
không có LIMIT
mệnh đề không ảnh hưởng đến đầu ra.
Trên Toàn bộ UNION
Truy vấn
Chúng tôi cũng có thể sử dụng ORDER BY
trên toàn bộ truy vấn, để toàn bộ đầu ra được sắp xếp cùng nhau.
Trong ví dụ này, chúng tôi lấy ví dụ trước đó và sắp xếp các kết quả được kết hợp:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2)
ORDER BY TeacherName DESC;
Kết quả:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 4 | Ein | | 5 | Bill | | 6 | Bill | | 2 | Ben | +-----------+-------------+
Ngay cả khi không sử dụng ORDER BY
mệnh đề trong mỗi SELECT
câu lệnh, mỗi SELECT
câu lệnh vẫn phải nằm trong ngoặc đơn và ORDER BY
mệnh đề (hoặc bất kỳ LIMIT
nào mệnh đề) phải ở sau mệnh đề cuối cùng.
(SELECT * FROM Teachers)
UNION
(SELECT * FROM Students)
ORDER BY TeacherName ASC;
Kết quả:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Xin lưu ý bạn, việc bỏ qua dấu ngoặc đơn sẽ tạo ra kết quả giống như kết quả có dấu ngoặc đơn:
SELECT * FROM Teachers
UNION
SELECT * FROM Students
ORDER BY TeacherName ASC;
Kết quả:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Lưu ý rằng nếu cột được sắp xếp sử dụng bí danh, thì cột đó phải được tham chiếu bằng bí danh của nó (không phải tên cột).
Ví dụ:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY t ASC;
Kết quả:
+--------+ | t | +--------+ | Ben | | Bill | | Cathy | | Ein | | Faye | | Jet | | Spike | | Warren | +--------+
Đây là những gì sẽ xảy ra nếu chúng tôi không sử dụng bí danh:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY TeacherName ASC;
Kết quả:
ERROR 1054 (42S22): Unknown column 'TeacherName' in 'order clause'
Số lượng Cột
Số cột được trả về bởi mỗi SELECT
tuyên bố phải giống nhau. Do đó, chúng tôi không thể làm những việc sau:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId, StudentName FROM Students;
Kết quả:
ERROR 1222 (21000): The used SELECT statements have a different number of columns
Loại dữ liệu
Các cột đã chọn được liệt kê ở các vị trí tương ứng của mỗi SELECT
câu lệnh phải có cùng kiểu dữ liệu. Tuy nhiên, nếu không, thì loại và độ dài của các cột trong UNION
kết quả có tính đến các giá trị được truy xuất bởi tất cả SELECT
tuyên bố.
Đây là những gì sẽ xảy ra nếu chúng tôi cố gắng kết hợp TeacherName
với StudentId
cột:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId FROM Students;
Kết quả:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | +-------------+
Một số RDBMS khác sẽ tạo ra lỗi trong trường hợp này, nhưng MySQL quản lý để tạo ra đầu ra mà không có lỗi.