it-swarm.com.de

Mehrere SQL-Spalten in IN-Klausel

Wenn Sie eine Tabelle basierend auf einer Gruppe von Werten für eine bestimmte Spalte abfragen müssen, können Sie einfach die IN-Klausel verwenden. 

Wenn jedoch eine Abfrage auf Basis mehrerer Spalten ausgeführt werden muss, können wir keine IN-Klausel verwenden (grepped in SO - Threads). 

Von anderen SO - Threads aus können wir dieses Problem mithilfe von Joins oder Exists-Klauseln usw. umgehen. Alle funktionieren jedoch, wenn sich sowohl Haupttabelle als auch Suchdaten in der Datenbank befinden. 

E.g
User table:
firstName, lastName, City

Angesichts einer Liste von (Vorname, Nachname) Tupeln muss ich die Städte abrufen. 

Ich kann mir folgende Lösungen vorstellen. 

1

Konstruieren Sie eine Auswahlabfrage wie 

SELECT city from user where (firstName=x and lastName=y) or (firstName=a and lastName=b) or .....

2

Laden Sie alle Werte für "firstName" und "lastName" in eine Staging-Tabelle hoch, und führen Sie einen Join zwischen der "user" -Tabelle und der neuen Staging-Tabelle durch. 

Gibt es Möglichkeiten, dieses Problem zu lösen, und welche Lösung ist für dieses Problem im Allgemeinen vorzuziehen?

29
Htaras

Das könnte man so machen:

SELECT city FROM user WHERE (firstName, lastName) IN (('a', 'b'), ('c', 'd'));

The sqlfiddle.

68
xdazz

Es ist oft einfacher, Ihre Daten in die Datenbank zu laden, selbst wenn nur eine schnelle Abfrage ausgeführt werden soll. Festcodierte Daten scheinen schnell einzugeben, werden jedoch schnell zum Schmerz, wenn Sie Änderungen vornehmen müssen.

Wenn Sie die Namen jedoch direkt in Ihre Abfrage eingeben möchten, können Sie dies einfacher tun:

with names (fname,lname) as (
    values
        ('John','Smith'),
        ('Mary','Jones')
)
select city from user
    inner join names on
        fname=firstName and
        lname=lastName;

Dies hat den Vorteil, dass Ihre Daten etwas von der Abfrage getrennt werden.

(Dies ist DB2-Syntax; möglicherweise müssen Sie einige Anpassungen an Ihrem System vornehmen.).

5
dan1111

In Oracle können Sie Folgendes tun:

SELECT * FROM table1 WHERE (col_a,col_b) IN (SELECT col_x,col_y FROM table2)
4
grokster

Stellen Sie sicher, dass Sie einen Index für die Spalten Vorname und Nachname haben, und gehen Sie zu 1. Dies hat wirklich keinen großen Einfluss auf die Leistung.

EDIT: Nach @Dems Kommentar zum Spamming des Plan-Cache könnte es eine bessere Lösung sein, eine berechnete Spalte für die vorhandene Tabelle (oder eine separate Ansicht) zu erstellen, die einen verketteten Firstname + Lastname-Wert enthielt, sodass Sie sie ausführen können eine Abfrage wie 

SELECT City 
FROM User 
WHERE Fullname in (@fullnames)

wobei @fullnames ein bisschen wie "'JonDoe', 'JaneDoe'" etc aussieht

1
Jaimal Chohan

Im Allgemeinen können Sie die Where-Condition einfach wie folgt schreiben:

select * from tab1
where (col1, col2) in (select col1, col2 from tab2)

Hinweis
Oracle ignoriert Zeilen, in denen eine oder mehrere der ausgewählten Spalten NULL sind. In diesen Fällen möchten Sie wahrscheinlich die Funktion NVL - verwenden, um NULL einem bestimmten Wert zuzuordnen (der nicht in den Werten enthalten sein sollte):

select * from tab1
where (col1, NVL(col2, '---') in (select col1, NVL(col2, '---') from tab2)

Oraclesql

1

Stellen Sie fest, ob die Liste der Namen bei jeder Abfrage anders ist oder wiederverwendet wird. Wenn es wiederverwendet wird, gehört es zur Datenbank.

Auch wenn es bei jeder Abfrage eindeutig ist, kann es aus Leistungsgründen sinnvoll sein, sie in eine temporäre Tabelle (#table-Syntax) zu laden. In diesem Fall können Sie die Neukompilierung einer komplexen Abfrage vermeiden.

Wenn die maximale Anzahl von Namen festgelegt ist, sollten Sie eine parametrisierte Abfrage verwenden.

Wenn jedoch keiner der oben genannten Fälle zutrifft, würde ich die Namen in der Abfrage wie in Ansatz Nr. 1 angeben.

0
Jirka Hanika