Trong SQL, UNION
mệnh đề nối kết quả của hai truy vấn thành một tập kết quả duy nhất.
Bạn có thể sử dụng UNION
mệnh đề có hoặc không có ALL
đối số:
-
UNION ALL
- Bao gồm các bản sao. -
UNION
- Loại trừ các bản sao.
Dưới đây là một số ví dụ cơ bản để chứng minh cách hoạt động của nó.
Bảng mẫu
Giả sử chúng ta có hai bảng:Cats
và Dogs
Cats
+---------+-----------+ | CatId | CatName | |---------+-----------| | 1 | Meow | | 2 | Fluffy | | 3 | Scratch | +---------+-----------+
Dogs
+---------+-----------+ | DogId | DogName | |---------+-----------| | 1 | Fetch | | 2 | Fluffy | | 3 | Wag | | 1002 | Fetch | +---------+-----------+
Chúng ta có thể sử dụng SELECT
câu lệnh với UNION
mệnh đề kết hợp các kết quả từ cả hai bảng thành một tập kết quả.
Ví dụ sử dụng UNION ALL
Đầu tiên, hãy sử dụng UNION ALL
để nó bao gồm các bản sao.
SELECT DogName AS PetName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats;
Kết quả:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Wag | | Fetch | | Meow | | Fluffy | | Scratch | +-----------+ (7 rows affected)
Trong trường hợp này, bảy hàng được trả về. Chúng ta có thể thấy rằng “Tìm nạp” được trả về hai lần. Điều này là do có hai con chó tên là Fetch.
Ngoài ra còn có một con mèo và một con chó cùng tên:Fluffy.
Lưu ý rằng tôi đã sử dụng bí danh cột để đặt tên cho trường mà thao tác trả về. Nếu tôi không làm điều đó, kết quả sẽ sử dụng tên cột từ truy vấn đầu tiên. Trong trường hợp đó, tiêu đề cột sẽ được gọi là DogName
thay vì PetName
.
SELECT DogName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats;
Kết quả:
+-----------+ | DogName | |-----------| | Fetch | | Fluffy | | Wag | | Fetch | | Meow | | Fluffy | | Scratch | +-----------+ (7 rows affected)
Điều này có thể được chấp nhận hoặc có thể không được chấp nhận, tùy thuộc vào dữ liệu bạn đang trả về trong truy vấn của mình. Trong trường hợp của chúng tôi, điều đó là không phù hợp, vì không phải tất cả các kết quả đều là chó.
Ví dụ sử dụng UNION
Hãy xem điều gì sẽ xảy ra khi chúng tôi xóa ALL
đối số.
SELECT DogName AS PetName
FROM Dogs
UNION
SELECT CatName
FROM Cats;
Kết quả:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Meow | | Scratch | | Wag | +-----------+ (5 rows affected)
Lần này chỉ có năm hàng được trả lại. Cả hai bản sao đều bị xóa.
UNION
so với DISTINCT
Lưu ý rằng điều này khác với việc áp dụng DISTINCT
cho từng SELECT
riêng lẻ tuyên bố. Nếu chúng tôi làm điều đó, Fluffy sẽ được trả lại hai lần, vì ALL
sẽ chỉ áp dụng cho SELECT
tuyên bố rằng nó đang được áp dụng chống lại (không phải cho các kết quả được nối).
Đây là một ví dụ để minh họa ý tôi muốn nói.
SELECT DISTINCT DogName AS PetName
FROM Dogs
UNION ALL
SELECT DISTINCT CatName
FROM Cats;
Kết quả:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Wag | | Fluffy | | Meow | | Scratch | +-----------+ (6 rows affected)
Tất cả các truy vấn phải trả về cùng một số cột
Khi bạn sử dụng UNION
, mỗi truy vấn phải có cùng số cột và chúng phải theo cùng một thứ tự.
Nếu không, bạn sẽ gặp lỗi.
SELECT CatName FROM Cats
UNION ALL
SELECT DogId, DogName FROM Dogs;
Kết quả:
Msg 205, Level 16, State 1, Line 1 All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
Đó là lỗi mà SQL Server trả về khi sử dụng số lượng cột không bằng nhau. Lỗi cụ thể này chỉ ra rằng hạn chế tương tự cũng áp dụng cho INTERSECT
và EXCEPT
các toán tử. Thông báo lỗi bạn nhận được có thể khác nhau, tùy thuộc vào DBMS của bạn.
Các loại dữ liệu phải tương thích
Ngoài việc yêu cầu cùng một số cột, các cột đó phải có kiểu dữ liệu tương thích.
Chúng không nhất thiết phải cùng một kiểu dữ liệu, nhưng chúng sẽ cần phải tương thích. Có nghĩa là, chúng phải tương thích thông qua chuyển đổi ngầm định. Nếu các loại dữ liệu không khớp, DBMS phải có thể thực hiện một chuyển đổi ngầm định để chúng khớp với nhau.
Nếu không, bạn sẽ gặp lỗi.
SELECT CatName FROM Cats
UNION ALL
SELECT DogId FROM Dogs;
Kết quả:
Msg 245, Level 16, State 1, Line 1 Conversion failed when converting the varchar value 'Meow' to data type int.
Sắp xếp kết quả
Nếu bạn muốn sắp xếp kết quả với ORDER BY
, bạn sẽ cần đặt nó vào truy vấn cuối cùng. Bạn không thể đặt một ORDER BY
riêng biệt trên mỗi truy vấn hoặc đối với vấn đề đó, bất kỳ truy vấn nào không phải là câu cuối cùng.
Đây là lỗi tôi gặp phải khi cố gắng thực hiện việc đó trong SQL Server:
SELECT DogName AS PetName
FROM Dogs
ORDER BY DogName
UNION ALL
SELECT CatName
FROM Cats;
Kết quả:
Msg 156, Level 15, State 1, Line 4 Incorrect syntax near the keyword 'UNION'.
Do đó, nếu chúng ta muốn sắp xếp các kết quả, chúng ta sẽ cần phải làm như sau:
SELECT DogName AS PetName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats
ORDER BY PetName;
Áp dụng UNION
cho nhiều hơn hai truy vấn
Các ví dụ trước đã kết hợp kết quả từ hai truy vấn khác nhau, nhưng không có gì ngăn bạn thêm nhiều hơn. Bạn có thể sử dụng nó để kết hợp kết quả của nhiều truy vấn nếu cần.
Ví dụ:nếu chúng ta cũng có Birds
bảng, chúng tôi có thể làm điều này:
SELECT DogName AS PetName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats
UNION ALL
SELECT BirdName
FROM Birds;
Chuẩn hóa
Các ví dụ trên trang này xếp mèo và chó vào hai bảng riêng biệt. Lý do tôi làm điều này là vì đó là một cách minh họa rõ ràng và ngắn gọn về cách UNION
hoạt động.
Trên thực tế, bạn có thể có những thứ này trong cùng một bảng được gọi là Pets
, sau đó có một PetTypes
riêng biệt bảng (hoặc tương tự). Đây được gọi là chuẩn hóa và là cách cơ sở dữ liệu quan hệ thường được thiết kế.
Sau đó, bạn có thể chạy một phép nối trên các bảng này để trả về dữ liệu theo yêu cầu.