Operasi perbedaan simetris dalam Transact-SQL?

10

Saya selalu tahu tentang UNIONoperator dalam SQL, tetapi hanya baru-baru ini menemukan bahwa ada set operator lain, INTERSECTdan EXCEPT. Saya belum dapat menemukan operator yang melakukan operator set besar keempat, perbedaan simetris (misalnya kebalikan dari INTERSECT.)

Sepertinya saya bisa mendapatkan output yang diinginkan dengan menggunakan sesuatu seperti

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

(dengan asumsi saya mendapat hak diutamakan), atau dengan melakukan anti-full-join:

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

Tetapi keduanya tampak seperti pertanyaan yang agak intensif, terutama dibandingkan dengan tiga operasi dasar lainnya. Apakah ada operasi perbedaan simetris dalam SQL dan saya tidak bisa menemukannya di dokumentasi? Atau apakah ada cara "kanonik" untuk mengimplementasikannya dalam T-SQL?

KutuluMike
sumber
2
(a EXCEPT b) UNION ALL (b EXCEPT a);mungkin lebih efisien.
ypercubeᵀᴹ
@ypercube yang melakukan 3 operasi join atau like. Saya tidak bisa memikirkan alasan apa pun ini mungkin lebih efisien daripada bergabung penuh.
usr
@ Usr itu sebenarnya 2 operasi seperti bergabung, bukan 3. Union All adalah operasi yang jauh lebih murah. Saya setuju itu FULL JOINmungkin lebih efisien. Pengujian dapat mengungkapkan mana yang terbaik. Dan tentu saja, jika lebih banyak / kolom berbeda dari setiap tabel diperlukan, solusi saya tidak mudah diperluas.
ypercubeᵀᴹ

Jawaban:

3

Semua operator yang ada diterjemahkan ke dalam operator bergabung atau suka. Anda dapat menyaksikannya dalam rencana kueri.

Karena alasan itu, sambungan luar sepenuhnya yang Anda miliki di sana adalah yang paling efisien yang dapat Anda lakukan. Mengabaikan, tentu saja, semoga situasi yang jarang terjadi di mana pengoptimal mengambil rencana yang buruk dan penulisan ulang terjadi untuk melakukan yang lebih baik karena keberuntungan. Ini selalu bisa terjadi.

usr
sumber
Itu masuk akal, bagaimanapun, alasan saya suka menggunakan set operator adalah karena mereka tidak membuat "kolom tambahan" ... Saya bisa melakukan hal-hal seperti SELECT Id FROM A WHERE <stuff> EXCEPT Select Id FROM A WHERE <other stuff>dan mendapatkan satu daftar Id. Saya tidak tahu bagaimana cara melakukannya dengan bergabung penuh ... apakah saya hanya perlu berurusan dengan memiliki dua set Idkolom dan menyatukannya kembali bersama?
KutuluMike
Bisa dibilang begitu ISNULL(a.Col, b.Col) AS Col. Bungkus itu dalam tabel turunan atau CTE dan Anda dapat menggunakan set hasil "terlipat" untuk operasi lebih lanjut. (Btw, saya setuju operator perbedaan simetris harus ada.)
usr
2
@MichaelEdenfield Di sisi lain, bagaimana bila Anda ingin kolom lain yang tidak digunakan dalam bandingkan / berbeda? Anda dapat melakukannya dengan bergabung tetapi tidak dengan memotong / kecuali. Jadi saya bisa melihat dalam beberapa kasus variasi akhirnya menjadi jauh lebih kompleks dalam jangka panjang.
Aaron Bertrand
2

Saya pikir ini adalah solusi yang cukup bagus. Ia menggunakan gabungan semua antara dua pilihan dengan sub-kueri Tidak Ada. Lebih baik daripada menggabungkan Serikat dan Kecuali karena Anda dapat menyertakan bidang yang tidak cocok dalam proyeksi.

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)
Darrel Lee
sumber