Ich versuche SQL zu lernen und habe Schwierigkeiten, EXISTS-Anweisungen zu verstehen. Ich bin auf dieses Zitat über "existiert" gestoßen und verstehe etwas nicht:
Mit dem Operator exist kann Ihre Unterabfrage null, eine oder viele Zeilen zurückgeben, und die Bedingung prüft einfach, ob die Unterabfrage Zeilen zurückgegeben hat. Wenn Sie sich die select-Klausel der Unterabfrage ansehen, werden Sie feststellen, dass sie aus einem einzelnen Literal besteht (1). Da die Bedingung in der enthaltenen Abfrage nur wissen muss, wie viele Zeilen zurückgegeben wurden, sind die tatsächlichen Daten, die die Unterabfrage zurückgegeben hat, irrelevant.
Was ich nicht verstehe, ist, woher die äußere Abfrage weiß, welche Zeile die Unterabfrage überprüft? Beispielsweise:
SELECT *
FROM suppliers
WHERE EXISTS (select *
from orders
where suppliers.supplier_id = orders.supplier_id);
Ich verstehe, dass wenn die ID aus der Lieferanten- und Auftragstabelle übereinstimmt, die Unterabfrage true zurückgibt und alle Spalten aus der übereinstimmenden Zeile in der Lieferantentabelle ausgegeben werden. Was ich nicht verstehe, ist, wie die Unterabfrage kommuniziert, welche bestimmte Zeile (sagen wir die Zeile mit der Lieferanten-ID 25) gedruckt werden soll, wenn nur ein wahres oder falsches zurückgegeben wird.
Es scheint mir, dass es keine Beziehung zwischen der äußeren Abfrage und der Unterabfrage gibt.
Was macht Ihrer Meinung nach die WHERE-Klausel im EXISTS-Beispiel? Wie kommen Sie zu diesem Schluss, wenn die SUPPLIERS-Referenz nicht in den FROM- oder JOIN-Klauseln der EXISTS-Klausel enthalten ist?
EXISTS bewertet TRUE / FALSE und wird bei der ersten Übereinstimmung der Kriterien als TRUE beendet - aus diesem Grund kann es schneller sein als
IN
. Beachten Sie auch, dass die SELECT-Klausel in einem EXISTS ignoriert wird - IE:... sollte eine Division durch Null Fehler treffen, wird es aber nicht. Die WHERE-Klausel ist das wichtigste Teil einer EXISTS-Klausel.
Beachten Sie auch, dass ein JOIN kein direkter Ersatz für EXISTS ist, da es doppelte übergeordnete Datensätze gibt, wenn dem übergeordneten Datensatz mehr als ein untergeordneter Datensatz zugeordnet ist.
quelle
EXISTS
Exits geben beim ersten Match TRUE zurück - da der Lieferant mindestens einmal in der Tabelle ORDERS vorhanden ist. Wenn Sie die Duplizierung der LIEFERANTEN-Daten sehen möchten, weil in ORDERS mehr als eine untergeordnete Beziehung vorhanden ist, müssen Sie JOIN verwenden. Die meisten möchten diese Duplizierung jedoch nicht, und das Ausführen von GROUP BY / DISTINCT kann zu einem zusätzlichen Aufwand für die Abfrage führen.EXISTS
ist effizienter alsSELECT DISTINCT ... FROM SUPPLIERS JOIN ORDERS ...
auf SQL Server, hat in letzter Zeit nicht auf Oracle oder MySQL getestet.Sie können identische Ergebnisse erzeugen entweder mit
JOIN
,EXISTS
,IN
, oderINTERSECT
:quelle
Wenn Sie eine where-Klausel hatten, die so aussah:
Sie können leicht verstehen, warum einige Zeilen zurückgegeben werden und andere nicht.
Wenn die where-Klausel so lautet:
es bedeutet nur: Zeilen zurückgeben, die einen vorhandenen Datensatz in der Auftragstabelle mit derselben ID haben.
quelle
Datenbanktabellenmodell
Nehmen wir an, wir haben die folgenden zwei Tabellen in unserer Datenbank, die eine Eins-zu-Viele-Tabellenbeziehung bilden.
Die
student
Tabelle ist die übergeordnete und diestudent_grade
untergeordnete Tabelle, da sie eine Fremdschlüsselspalte student_id enthält, die auf die ID-Primärschlüsselspalte in der Schülertabelle verweist.Das
student table
enthält die folgenden zwei Datensätze:In der
student_grade
Tabelle sind die Noten aufgeführt, die die Schüler erhalten haben:SQL EXISTIERT
Nehmen wir an, wir möchten alle Schüler erreichen, die im Mathematikunterricht eine Note von 10 erhalten haben.
Wenn wir nur an der Studentenkennung interessiert sind, können wir eine Abfrage wie diese ausführen:
Die Anwendung ist jedoch daran interessiert, den vollständigen Namen von a anzuzeigen
student
, nicht nur den Bezeichner. Daher benötigen wir auch Informationen aus derstudent
Tabelle.Um die
student
Datensätze mit einer Note von 10 in Mathematik zu filtern , können Sie den EXISTS SQL-Operator wie folgt verwenden:Wenn Sie die obige Abfrage ausführen, sehen Sie, dass nur die Alice-Zeile ausgewählt ist:
Die äußere Abfrage wählt die
student
Zeilenspalten aus, die an den Client zurückgegeben werden sollen. Die WHERE-Klausel verwendet jedoch den EXISTS-Operator mit einer zugehörigen inneren Unterabfrage.Der EXISTS-Operator gibt true zurück, wenn die Unterabfrage mindestens einen Datensatz zurückgibt, und false, wenn keine Zeile ausgewählt ist. Das Datenbankmodul muss die Unterabfrage nicht vollständig ausführen. Wenn ein einzelner Datensatz übereinstimmt, gibt der EXISTS-Operator true zurück und die zugehörige andere Abfragezeile wird ausgewählt.
Die innere Unterabfrage ist korreliert, da die Spalte student_id der
student_grade
Tabelle mit der Spalte id der äußeren Schülertabelle abgeglichen wird.quelle
EXIST
nur mit korrelierten Unterabfragen? Ich habe mit Abfragen herumgespielt, die nur 1 Tabelle enthieltenSELECT id FROM student WHERE EXISTS (SELECT 1 FROM student WHERE student.id > 1)
. Ich weiß, was ich geschrieben habe, kann durch eine einfache WHERE-Abfrage erreicht werden, aber ich habe es nur verwendet, um EXISTS zu verstehen. Ich habe alle Reihen. Liegt es tatsächlich daran, dass ich keine korrelierte Unterabfrage verwendet habe? Vielen Dank.EXISTS bedeutet, dass die Unterabfrage mindestens eine Zeile zurückgibt, das ist es wirklich. In diesem Fall handelt es sich um eine korrelierte Unterabfrage, da die Lieferanten-ID der äußeren Tabelle mit der Lieferanten-ID der inneren Tabelle überprüft wird. Diese Abfrage besagt im Endeffekt:
Alle Lieferanten AUSWÄHLEN Überprüfen Sie für jede Lieferanten-ID, ob für diesen Lieferanten eine Bestellung vorhanden ist. Wenn der Lieferant nicht in der Auftragstabelle vorhanden ist, entfernen Sie den Lieferanten aus den Ergebnissen. RÜCKGABE aller Lieferanten, die entsprechende Zeilen in der Auftragstabelle haben
In diesem Fall können Sie dasselbe mit einem INNER JOIN tun.
Ponys Kommentar ist richtig. Sie müssen mit diesem Join eine Gruppierung durchführen oder je nach den von Ihnen benötigten Daten unterschiedliche auswählen.
quelle
Was Sie beschreiben, ist eine sogenannte Abfrage mit einer korrelierten Unterabfrage .
(Im Allgemeinen) sollten Sie versuchen, dies zu vermeiden, indem Sie die Abfrage stattdessen mit einem Join schreiben:
Andernfalls wird die Unterabfrage für jede Zeile in der äußeren Abfrage ausgeführt.
quelle
orders
der Join-Bedingung vorhanden ist.