Frage

Ich habe gerade gelernt ( gestern ) verwenden Sie "existiert" statt "in".

 BAD
 select * from table where nameid in ( 
          select nameid from othertable where otherdesc =  'SomeDesc' )      
 GOOD
 select * from table t where exists ( 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeDesc' )      

Und ich habe einige Fragen dazu:

1) Die Erklärung wie ich verstanden habe war: "Der Grund, warum dies besser ist, da nur der entsprechende Werte wird zurückgegeben, anstatt eine riesige Liste der möglichen Ergebnisse".Heißt das, dass, während die erste Unterabfrage zurückgibt 900 Ergebnisse der zweiten Rückkehr wird nur 1 ( ja oder Nein )?

2) In der Vergangenheit hatte ich das RDBMS complainin:"nur die ersten 1000 Zeilen kann abgerufen werden", dieser zweite Ansatz würde das problem lösen?

3) Was ist der Umfang des alias in der zweiten Unterabfrage?...funktioniert der alias nur lebt in der Klammer?

zum Beispiel

 select * from table t where exists ( 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeDesc' )      
 AND 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeOtherDesc' )      

Das ist, wenn ich den gleichen alias ( o für Tisch othertable ) In der zweiten "existieren" wird es kein problem mit die erste existiert?oder sind Sie völlig unabhängig?

Ist das etwas, das nur Oracle im Zusammenhang oder ist es nur gültig für die meisten RDBMS?

Vielen Dank

War es hilfreich?

Lösung

Es ist spezifisch für jedes DBMS und hängt von den Abfrageoptimierer.Einige Optimierer erkennen, die IN-Klausel und übersetzen Sie es.

In alle DBMS, die ich getestet habe, alias ist nur gültig innerhalb der ( )

BTW, Sie können die Abfrage so umschreiben, wie:

select t.* 
from table t 
join othertable o on t.nameid = o.nameid 
    and o.otherdesc in ('SomeDesc','SomeOtherDesc');

Und, um Ihre Fragen zu beantworten:

  1. Ja
  2. Ja
  3. Ja

Andere Tipps

Sie treten in komplizierte Gebiet, bekannt als 'korrelierte sub-queries'.Da wir nicht über detaillierte Informationen über Ihre Tabellen und die Taste Strukturen, die Antworten nur "vielleicht".

In Ihrer ersten Abfrage IN der notation würde gültig sein, ob oder nicht OtherTable enthält eine Spalte NameID (und, in der Tat, ob OtherDesc existiert als eine Spalte in der Tabelle oder OtherTable - was nicht klar ist in jedem der Beispiele, vermutlich aber ist Sie eine Spalte OtherTable).Dieses Verhalten ist, was macht ein correlated sub-query in a correlated sub-query.Es ist auch eine routine, die Quelle der angst für die Menschen, wenn Sie zum ersten Lauf in es - immer durch Zufall.Da der SQL-standard Mandate das Verhalten der Interpretation einen Namen in der sub-query, als Verweis auf eine Spalte in der äußeren Abfrage, wenn es ist keine Spalte mit dem entsprechenden Namen, die in den Tabellen erwähnt in der sub-query, aber es gibt eine Spalte mit dem entsprechenden Namen, die in den Tabellen genannten, in den äußeren (main) - Abfrage, kein Produkt behaupten möchte, Konformität (dieses Stück) der SQL-standard wird alles tun, anders.

Die Antwort auf Ihre Q1 ist "es hängt", aber plausiblen Annahmen (NameID existiert als eine Spalte in beiden Tabellen;OtherDesc existiert nur in OtherTable), die Ergebnisse sollten die gleichen sein, in Bezug auf den Datensatz zurückgegeben, die aber nicht gleichwertig in Bezug auf die Leistung.

Die Antwort auf Ihre Q2 ist, dass in der Vergangenheit, Sie waren mit einem minderwertigen, wenn nicht defekt DBMS.Wenn es unterstützt, VORHANDEN ist, dann das DBMS kann immer noch beschweren sich über die Kardinalität des Ergebnisses.

Die Antwort auf Ihre Q3 wie Sie auf den ersten EXISTS-Abfrage ist "t ist verfügbar als alias in der gesamten Anweisung, aber o ist nur als alias in Klammern".Wie Sie auf Ihrem zweiten Beispiel box - mit UND anschließen von zwei sub-selects (von denen die zweite fehlt der offenen Klammer, wenn ich bin, es zu betrachten), dann "t ist verfügbar als alias in der gesamten Aussage und bezieht sich auf die gleiche Tabelle, aber es gibt zwei verschiedene Aliase, beide mit der Aufschrift "o', eine für jede sub-query".Beachten Sie, dass die Abfrage möglicherweise keine Daten zurückgeben, wenn OtherDesc ist einzigartig für eine bestimmte NameID Wert in OtherTable;andernfalls ist es erforderlich, zwei Zeilen in OtherTable mit der gleichen NameID, und die beiden OtherDesc Werte für jede Zeile in der Tabelle mit NameID Wert.

  1. Oracle-spezifisch:Wenn Sie eine Abfrage schreiben, mit der IN-Klausel, du erzählst der regelbasierte Optimierer, dass Sie möchten, dass die innere Abfrage für den Antrieb der äußeren Abfrage.Wenn Sie schreiben, BESTEHT in einer where-Klausel, du erzählst der Optimierer, dass Sie möchten, dass die äußeren Abfrage ausgeführt werden, der erste ist, jeden Wert zu Holen ein Wert aus der inneren Abfrage.Finden "Unterschied zwischen" IN "und EXISTIERT in Unterabfragen".
  2. Wahrscheinlich.
  3. Alias deklariert innere Unterabfrage lebt in Unterabfrage.Übrigens, ich glaube nicht, dass dein Beispiel mit 2 ANDed Unterabfragen gültig ist SQL.Du meinst UNION statt UND?

Persönlich würde ich verwenden Sie eine Verknüpfung, anstatt eine Unterabfrage für diese.

SELECT t.*
FROM yourTable t
    INNER JOIN otherTable ot
        ON (t.nameid = ot.nameid AND ot.otherdesc = 'SomeDesc')

Es ist schwierig zu verallgemeinern, was EXISTIERT, ist immer besser als IN.Logisch, wenn das der Fall ist, dann SQL-Gemeinschaft ersetzt, mit IST...Auch, bitte beachten Sie, dass es IN und es gibt nicht die gleichen, die Ergebnisse können unterschiedlich sein, wenn Sie die zwei...

Mit IN der Regel seine ein Full Table Scan der inneren Tabelle einmal ohne entfernen der Nullen (also, wenn Sie Null-Werte in Ihrem inneren Tabelle, IN der nicht entfernt wird standardmäßig NULL)...Zwar EXISTIERT, entfernt, für NULL und im Falle von korrelierten Unterabfrage, es läuft innere Abfrage für jede Zeile der äußeren Abfrage.

Vorausgesetzt, es gibt keine NULL-Werte und eine einfache Abfrage (keine Korrelation), EXISTIEREN möglicherweise besser aus, wenn die Zeile, die Sie finden, ist nicht die Letzte Zeile.Wenn es passiert, werden Sie in der letzten Zeile, EXISTIERT kann Scannen bis zum Ende, wie IN..so ähnliche performance -...

Aber IN der EXISTIERT und nicht austauschbar...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top