2016-12-07 3 views
2

Ist so etwas möglich (ich weiß, diese Aussage nicht funktioniert, ich habe es versucht):SELECT * FROM t WHERE tx ODER ty IN (id FROM z SELECT)

SELECT * FROM t WHERE t.x OR t.y IN (SELECT id FROM z) 

Beispiel

Tabelle t:

|id|x |y 
|1 |101|201 
|2 |102|202 

Tabelle z:

|id | 
|101 | 
|201 | 

Und von dieser Tabelle t möchte ich alle Einträge auswählen, in denen entweder das Attribut x oder das Attribut y in der Liste der IDs von Tabelle z enthalten ist.

ich weiß, ich

SELECT * FROM t WHERE t.x IN (SELECT id FROM z) OR t.y IN (SELECT id FROM z) 

tun können, aber das fühlt sich an wie es sehr ineffizient ist, wenn die IN Werte aus einer komplexen Unterabfrage kommen (was dann ist das gleiche in beiden IN Klauseln).

Oder sind aktuelle Abfrageplaner-Implementierungen so clever, dass beide Unterabfragen die gleichen Ergebnisse liefern und nur einmal ausgeführt werden? Oder gibt es eine andere Lösung mit EXISTS, die ich derzeit nicht sehe?

PS: Ich benutze Postgres, aber ich suche nach einer generischen Lösung.

Antwort

4

Verwenden EXISTS

SELECT * FROM t WHERE exists (SELECT 1 FROM z where z.id in (t.x,t.y)) 
+0

funktioniert perfekt ... danke! – unwichtich

1

Wenn z eine komplexe Abfrage ist, dann können Sie einen CTE verwenden Sie den Code zu vereinfachen:

WITH z AS (
     . . . 
    ) 
SELECT * 
FROM t 
WHERE t.x IN (SELECT id FROM z) OR t.y IN (SELECT id FROM z); 

Sie können auch JOIN oder EXISTS statt:

SELECT * 
FROM t 
WHERE EXISTS (SELECT 1 
       FROM z 
       WHERE z.id IN (t.x, t.y) 
      ); 

Die JOIN Version hat den Nachteil, dass Zeilen aufgrund von Duplikaten in z multiplizieren können.

Das heißt, die Version mit den zwei IN Ausdrücke ist möglicherweise die effizienteste. Versuchen

0

...

SELECT t.* FROM t join z on t.x = z.id or t.y = z.id 
+0

Dies ist nicht unbedingt das Gleiche –

+0

Dies könnte zu doppelten Datensätzen führen, wenn id in 'z' Tabelle dupliziert wird –

+0

Dann können Sie' distinct' verwenden, falls erforderlich. –

Verwandte Themen