Vergleichen Sie 4 oder mehr Spaltenwerte

7

Ich habe einen Tisch wie:

ID   A0  A1  A2 A3 A4
14   A   B   A  C  A
15   A   A   A  A  A

Ich muss alle 5 Spalten vergleichen und prüfen, ob sie denselben Wert haben, und die einzige abrufen, die alle gleichen Werte hat. In diesem Fall die mit der ID 15. Gibt es eine Möglichkeit, dies in T-SQL zu erreichen?

user68859
quelle

Antworten:

12

Ich bin nicht mit der SQL-Marke von SQL Server vertraut, aber es muss ungefähr so ​​aussehen:

SELECT ID FROM My_Table 
WHERE 
(A0 = A1) AND
(A1 = A2) AND
(A2 = A3) AND
(A3 = A4);

Schauen Sie sich diese dbfiddle.uk an, die alle Antworten im Antwort-Thread zeigt.

Vérace
quelle
11

Angesichts der Beispieldaten:

CREATE TABLE dbo.Data
(
    ID integer PRIMARY KEY,
    A0 character(1) NULL,
    A1 character(1) NULL,
    A2 character(1) NULL,
    A3 character(1) NULL,
    A4 character(1) NULL
);

INSERT dbo.Data
    (ID, A0, A1, A2, A3, A4)
VALUES
    (14, 'A', 'B', 'A', 'C', 'A'),
    (15, 'A', 'A', 'A', 'A', 'A');

Eine alternative Möglichkeit, alle Nicht-ID-Spalten auf Gleichheit zu vergleichen, ist:

SELECT
    D.*
FROM dbo.Data AS D
WHERE EXISTS
(
    -- All columns except the last one
    SELECT D.A0, D.A1, D.A2, D.A3
    INTERSECT
    -- All columns except the first one
    SELECT D.A1, D.A2, D.A3, D.A4
);

Wenn viele Spalten vorhanden sind, ist dies möglicherweise einfacher zu schreiben als eine Abfrage mit mehreren ANDKlauseln (und häufig kompakter). In Management Studio können Sie den Knoten Spalten aus dem Objekt-Explorer in ein Textfenster ziehen, um eine durch Kommas getrennte Spaltenliste zu erstellen. Das Versetzen dieser Liste für den zweiten Teil von INTERSECTist ebenfalls trivial.

Der durch diese Abfrage generierte Ausführungsplan ist genauso effizient wie die ANDVersion mit mehreren Klauseln. Semantisch unterscheidet es sich geringfügig darin, dass NULLDatenelemente gleich miteinander verglichen werden.

Ausführungsplan

Paul White 9
quelle
5

Ich kann eine andere Lösung vorschlagen. Sie können verwenden COMPUTED COLUMN. Dies ist natürlich der Fall, wenn Sie die Tabellenstruktur ändern können und wenn Sie diesen Vergleich sehr oft durchführen.

Innerhalb des können COMPUTED COLUMNSie berechnen, ob alle zu vergleichenden Spalten dieselben Daten enthalten boolean value. Danach vergleichen Sie nur diesen Wert in Ihren Abfragen.

Auch wenn Sie persistent optionden Wert einstellen, wird er bei jeder Datenänderung berechnet und gespeichert. In diesem Fall entsteht Speicheraufwand.

Über COMPUTED COLUMNSSie können zum Beispiel hier lesen

EDIT: Wie verace und Ian Ringrose bemerkt - wenn es eine ist filtered indexauf COMPUTED COLUMN(in diesem Fall muss es sein persistent) , können Sie die Leistung profitieren. Natürlich muss genügend Daten vorhanden sein.

Bogdan Bogdanov
quelle
1
+1 dafür. Es kann sehr nützlich sein, wenn die Spalten A0 - A4 nicht indiziert sind / nicht indiziert werden können - die Abfrage ist möglicherweise viel schneller.
Vérace
10x, @ Vérace. Ich denke nicht über diese Art von Anwendung nach.
Bogdan Bogdanov
1
Dies ist nur dann von Vorteil, wenn COMPUTED COLUMN indiziert ist. Ein gefilterter Index auf SQL Server eignet sich hervorragend dafür. (Nur Indexzeilen, in denen die Spalte 1 ist)
Ian Ringrose
Ja, @Ian Ringrose natürlich.
Bogdan Bogdanov
Ich kann die Tabellenstruktur nicht ändern ... irgendeine andere Idee?
user68859
3

Ein weiteres Beispiel mit cross apply. Die Idee ist, a0, a1, ... in Zeilen zu transponieren und dann zu überprüfen, wo max und min gleich sind:

select d.id 
from dbo.data as d
cross apply ( values (d.a0),(d.a1),(d.a2),(d.a3),(d.a4) ) as x(a)
group by d.id
having min(a) = max(a);
Lennart
quelle