Filtern mit mehrzeiligem Subselect

RfgsWlcm2k17

Lt. Junior Grade
Registriert
Sep. 2016
Beiträge
485
editiert
 
Zuletzt bearbeitet:
editiert
 
Zuletzt bearbeitet:
Aufpassen, daß da nichts korreliert, ie die Unterabfrage sich nicht auf äußere Abfragen bezieht => ganz schlecht für die Performance.

“Normal” kann man meist auf solche Subselects verzichten und das in Joins und WHERE der eigentlichen Abfrage schieben. Ist sauberer und performanter.
 
Wenn keine Zusatzdaten aus der Tabelle gebraucht werde, sollte man auf einen Join verzichten. Dieser kann je nach Ausführungplan mehr kosten als ein Abgleich mit NOT IN. Je nach Situation, kann auch ein NOT EXISTS sinnvoll sein, wenn z.B. ein Delta-Abgleich zwischen Faktentabellen benötigt wird. Das scheint mir hier aber nicht der Fall zu sein.

Am Ende muss man sich natürlich den Ausführungsplan anschauen und abwägen.
 
Zuletzt bearbeitet:
editiert
 
Zuletzt bearbeitet:
parats schrieb:
Wenn keine Zusatzdaten aus der Tabelle gebraucht werde, sollte man auf einen Join verzichten. Dieser kann je nach Ausführungplan mehr kosten als ein Abgleich mit NOT IN.

Je nach DBMS. Ich hab keine Lust auf NOT IN auf der einen und NULL auf der anderen Seite. Klar, kann man alles machen, man muß dann aber auch die Eigenheiten kennen.

@RfgsWlcm2k17 will ich wissen, was da abgeht? :) Klingt so, als wäre das exakt nicht mein Metier; bei mir haben Daten "vernünftig", ie halbwegs normalisiert vorzuliegen, außer es wäre ein Fall von OLAP.

Wenn es so geht, dann ist gut. Problem bei korrelierten Subselects ist halt, daß eine (oder gar mehr) Abfrage pro Ergebnisdatensatz ausgeführt werden muß. Viele Datensätze und man kommt ganz schnell auf zehntausende zusätzliche Abfragen, die man mit ein bißchen geschickterer Abfragestruktur vielleicht hätte vermeiden können.

Subselects sind aber natürlich nicht alle korreliert. Hier ein Beispiel, wie es nicht aussehen sollte:

SQL:
SELECT colA, colB from table1 T1 WHERE colC = ANY(SELECT id FROM table2 WHERE id = T1.colD)

Stattdessen kann man ein JOIN bauen anhand des Subselect-Kriterums und so die Korrelation aufheben:

SQL:
SELECT colA, colB from table1 T1 
JOIN table2 T2 ON T2.id = T1.colD -- hier wird table2 der ursprünglichen table1 gegenübergestellt, das bildet das Subselect ab
 WHERE T1.colC = T1.colD -- die Entsprechung der WHERE-Klausel oben, nur daß jetzt table2 bereits gegenübergestellt ist; daher können wir zeilenweise vergleichen und brauchen ANY nicht mehr

Note, je nach DBMS ist statt = ANY(...) einfach IN(...) zu verwenden.

NOT IN(...) hat das Problem, daß elementweise verglichen wird und NULL-Werte einen Sonderfall ergeben. Operationen mit NULL ergeben NULL, entsprechend ist x IN (NULL) dasselbe wie x NOT IN (NULL), nämlich NULL.
NOT IN(...) kann man daher nur zuverlässig auf Spalten legen, die selber ein NOT NULL-Flag gesetzt haben. Ansonsten geht das irgendwann schief.
 
  • Gefällt mir
Reaktionen: RfgsWlcm2k17
Wenn wir von Dimensionen zu Fakten reden, dann gibt es bitte immer einen default Wert und kein NULL. Sprich wenn nichts vergeben dann bspw. -1 mit einem String wie N/A als Label in der Dimension und die Spalte selbst in der Faktentabelle ist als NOT NULL geflagged...
 
Zurück
Oben