Symmetrische Differenzoperation in Transact-SQL?

9

Ich habe immer über den UNIONOperator in SQL gewusst , aber erst kürzlich festgestellt, dass es andere Mengenoperatoren gibt, INTERSECTund EXCEPT. Ich konnte keinen Operator finden, der den vierten großen Mengenoperator ausführt, den symmetrischen Unterschied (z INTERSECT. B. das Gegenteil von .)

Es sieht so aus, als könnte ich mit so etwas die gewünschte Ausgabe erzielen

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

(vorausgesetzt, ich habe den richtigen Vorrang) oder durch einen 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

Beide sehen jedoch nach ziemlich intensiven Abfragen aus, insbesondere im Vergleich zu den anderen drei grundlegenden Mengenoperationen. Gibt es eine symmetrische Differenzoperation in SQL und ich kann sie in der Dokumentation einfach nicht finden? Oder gibt es eine "kanonische" Möglichkeit, es in T-SQL zu implementieren?

KutuluMike
quelle
2
(a EXCEPT b) UNION ALL (b EXCEPT a);könnte effizienter sein.
Ypercubeᵀᴹ
@ypercube, der 3 Verknüpfungen oder verbindungsähnliche Operationen ausführt. Ich kann mir keinen Grund vorstellen, warum dies effizienter sein könnte als ein vollständiger Join.
usr
@usr es sind eigentlich 2 Join-ähnliche Operationen, nicht 3. Union All ist eine viel kostengünstigere Operation. Ich bin damit einverstanden, dass FULL JOINdies effizienter sein kann. Tests können zeigen, welches am besten ist. Und wenn mehr / unterschiedliche Spalten aus jeder Tabelle benötigt werden, ist meine Lösung natürlich nicht einfach zu erweitern.
Ypercubeᵀᴹ

Antworten:

3

Alle Set-Operatoren werden in Joins oder Join-ähnliche Operatoren übersetzt. Sie können dies im Abfrageplan sehen.

Aus diesem Grund ist die vollständige äußere Verknüpfung, die Sie dort haben, die effizienteste, die Sie ausführen können. Wenn man natürlich die hoffentlich seltene Situation außer Acht lässt, in der der Optimierer einen schlechten Plan auswählt und ein Umschreiben durch Glück besser abschneidet. Das kann immer passieren.

usr
quelle
Das macht Sinn, aber der Grund, warum ich die Set-Operatoren gerne benutze, ist, dass sie keine "zusätzlichen Spalten" erstellen ... Ich kann Dinge wie tun SELECT Id FROM A WHERE <stuff> EXCEPT Select Id FROM A WHERE <other stuff>und eine einzelne Liste von erhalten Id. Ich kann nicht herausfinden, wie ich das mit einer vollständigen Verknüpfung machen soll ... muss ich mich nur darum kümmern, zwei Sätze von IdSpalten zu haben und sie selbst wieder zusammenzufügen?
KutuluMike
Das kannst du sagen ISNULL(a.Col, b.Col) AS Col. Wickeln Sie das in eine abgeleitete Tabelle oder einen CTE ein, und Sie können die "gefaltete" Ergebnismenge für die weitere Bearbeitung verwenden. (Übrigens stimme ich zu, dass der symmetrische Differenzoperator existieren sollte.)
usr
2
@MichaelEdenfield Was ist dagegen, wenn Sie andere Spalten möchten , die im Vergleich / Unterscheidungsmerkmal nicht verwendet werden? Sie können dies mit einem Join tun, aber nicht mit intersect / exception. So konnte ich in einigen Fällen sehen, dass Variationen auf lange Sicht tatsächlich viel komplexer werden.
Aaron Bertrand
2

Ich denke, das ist eine ziemlich gute Lösung. Es wird eine Vereinigung aller zwei Auswahlen mit Unterabfragen "Nicht vorhanden" verwendet. Besser als Union und Except zu kombinieren, da Sie Felder, die nicht übereinstimmen, in die Projektion aufnehmen können.

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
quelle