Hoạt động khác biệt đối xứng trong Transact-SQL?


9

Tôi đã luôn biết về UNIONtoán tử trong SQL, nhưng chỉ gần đây mới phát hiện ra rằng có các toán tử tập hợp khác INTERSECTEXCEPT. Tôi chưa thể tìm thấy một toán tử nào thực hiện toán tử tập lớn thứ tư, sự khác biệt đối xứng (ví dụ ngược lại INTERSECT.)

Có vẻ như tôi có thể có được đầu ra mong muốn bằng cách sử dụng một cái gì đó như

SELECT Field FROM A UNION SELECT Field FROM B 
EXCEPT
SELECT Field FROM A INTERSECT SELECT Field FROM B

(giả sử tôi có quyền ưu tiên) hoặc bằng cách thực hiện chống tham gia đầy đủ:

SELECT A.Field, B.Field
FROM A
FULL JOIN B ON B.Id = A.Id
WHERE B.Id IS NULL OR A.Id IS NULL

Nhưng cả hai đều trông giống như các truy vấn khá chuyên sâu, đặc biệt là so với ba thao tác thiết lập cơ bản khác. Có một hoạt động khác biệt đối xứng trong SQL và tôi không thể tìm thấy nó trong tài liệu? Hoặc có cách "chính tắc" nào để triển khai nó trong T-SQL không?


2
(a EXCEPT b) UNION ALL (b EXCEPT a);có thể hiệu quả hơn
ypercubeᵀᴹ

@ypercube có 3 hoạt động tham gia hoặc hoạt động giống như tham gia. Tôi không thể nghĩ ra bất kỳ lý do nào điều này có thể hiệu quả hơn là tham gia đầy đủ.
usr

@usr thực sự là 2 hoạt động giống như tham gia, không phải 3. Union All là hoạt động ít tốn kém hơn nhiều. Tôi đồng ý rằng FULL JOINcó thể hiệu quả hơn. Kiểm tra có thể tiết lộ đó là tốt nhất. Và tất nhiên, nếu cần nhiều hơn / các cột khác nhau từ mỗi bảng, giải pháp của tôi không dễ dàng mở rộng.
ypercubeᵀᴹ

Câu trả lời:


3

Tất cả các toán tử tập hợp được dịch thành các phép nối hoặc các toán tử giống như tham gia. Bạn có thể chứng kiến ​​điều đó trong kế hoạch truy vấn.

Vì lý do đó, tham gia bên ngoài đầy đủ mà bạn có có hiệu quả nhất bạn có thể làm. Tất nhiên, không quan tâm đến tình huống hiếm gặp hy vọng trong đó trình tối ưu hóa chọn một kế hoạch xấu và viết lại xảy ra để thực hiện tốt hơn nhờ may mắn. Điều này luôn có thể xảy ra.


Tuy nhiên, điều đó có ý nghĩa, lý do tôi thích sử dụng các toán tử tập hợp là vì chúng không tạo ra "cột bổ sung" ... Tôi có thể làm những việc như thế SELECT Id FROM A WHERE <stuff> EXCEPT Select Id FROM A WHERE <other stuff>và có được một danh sách duy nhất Id. Tôi không thể tìm ra cách để làm điều đó với một sự tham gia đầy đủ ... tôi chỉ cần đối phó với việc có hai bộ Idcột và liên kết chúng lại với nhau?
KutuluMike

Bạn có thể nói ISNULL(a.Col, b.Col) AS Col. Gói nó trong một bảng dẫn xuất hoặc CTE và bạn có thể sử dụng tập kết quả "được gấp lại" để tiếp tục thao tác trên nó. (Btw, tôi đồng ý rằng toán tử chênh lệch đối xứng nên tồn tại.)
usr

2
@MichaelEdenfield Mặt khác, khi bạn muốn các cột khác không được sử dụng trong so sánh / khác biệt thì sao? Bạn có thể làm điều đó với một tham gia nhưng không phải với giao cắt / ngoại trừ. Vì vậy, tôi có thể thấy trong một số trường hợp, sự thay đổi thực sự trở nên phức tạp hơn nhiều trong thời gian dài.
Aaron Bertrand

2

Tôi nghĩ rằng đây là một giải pháp khá tốt. Nó sử dụng một liên kết tất cả giữa hai lựa chọn với các truy vấn phụ Không tồn tại. Tốt hơn là kết hợp Liên minh và Ngoại trừ vì bạn có thể bao gồm các trường không khớp trong phép chiếu.

SELECT  'A' TableName, FileType FROM KFX_Inventory I 
    WHERE Not Exists (Select Top 1 1 from KFX_FileType FT WHERE FT.FileType = I.FileType)
UNION ALL
SELECT  'B', FileType FROM KFX_FILEType FT 
    WHERE Not Exists (Select Top 1 1 from KFX_Inventory I WHERE FT.FileType = I.FileType)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.