Eine Unterabfrage ist eine SQL-Abfrage (Structured Query Language), die in einer anderen SQL-Abfrage verschachtelt ist. Der Befehl, in dem die Unterabfrage verschachtelt ist, wird als übergeordnete Abfrage bezeichnet. Unterabfragen werden verwendet, um Daten vorzuverarbeiten, die in der übergeordneten Abfrage verwendet werden. Unterabfragen können in SELECT
angewendet werden , INSERT
, UPDATE
, und DELETE
Operationen.
Wenn Unterabfragen ausgeführt werden, wird die Unterabfrage zuerst vor der übergeordneten Abfrage verarbeitet. Beim Erstellen von MySQL-Anwendungen bietet die Verwendung von Unterabfragen mehrere Vorteile:
- Sie unterteilen die SQL-Anweisungen in einfache logische Einheiten, wodurch sie leichter zu verstehen und zu warten sind. Mit anderen Worten, Unterabfragen helfen dabei, komplexe Teile von Abfragen zu isolieren.
- Sie beseitigen die Notwendigkeit, komplexe
UNION
zu verwenden Anweisungen undJOIN
Aussagen. - Sie werden verwendet, um die referenzielle Integrität in einem Szenario zu erzwingen, in dem keine Fremdschlüssel implementiert sind.
- Sie helfen Entwicklern, Geschäftslogik in die MySQL-Abfragen zu codieren.
In diesem Handbuch erfahren Sie:
- So verwenden Sie eine korrelierte Unterabfrage
- Verwendung einer korrelierten Unterabfrage in einem Vergleichsoperator
- So verwenden Sie eine Unterabfrage als abgeleitete Tabelle
Bevor Sie beginnen
Um dieser Anleitung zu folgen, stellen Sie sicher, dass Sie Folgendes haben:
-
Wenn Sie dies noch nicht getan haben, erstellen Sie ein Linode-Konto und eine Compute-Instanz. Sehen Sie sich unsere Leitfäden Erste Schritte mit Linode und Erstellen einer Compute-Instanz an.
-
Folgen Sie unserem Leitfaden zum Einrichten und Sichern einer Compute-Instanz, um Ihr System zu aktualisieren. Möglicherweise möchten Sie auch die Zeitzone festlegen, Ihren Hostnamen konfigurieren, ein eingeschränktes Benutzerkonto erstellen und den SSH-Zugriff sichern.
-
Die MySQL-Serversoftware (oder MariaDB), die auf Ihrem Linode installiert ist. Bitte lesen Sie den MySQL-Abschnitt, der Anleitungen enthält, die beschreiben, wie MySQL auf mehreren Linux-Distributionen installiert wird.
Einrichten der Datenbank
Um zu verstehen, wie Unterabfragen funktionieren, erstellen Sie zunächst eine Beispieldatenbank. Diese Beispieldatenbank wird verwendet, um die verschiedenen Beispielabfragen in diesem Handbuch auszuführen:
-
SSH
zu Ihrem Server und melden Sie sich als root bei MySQL an:mysql -u root -p
Wenn Sie dazu aufgefordert werden, geben Sie das Root-Passwort Ihres MySQL-Servers ein und drücken Sie Enter weitermachen. Beachten Sie, dass das Root-Passwort Ihres MySQL-Servers nicht dasselbe ist wie das Root-Passwort für Ihr Linode.
Hinweis
Wenn Ihr Passwort nicht akzeptiert wird, müssen Sie möglicherweise den vorherigen Befehl mit
sudo
ausführen :sudo mysql -u root -p
-
Wenn Ihr Passwort akzeptiert wird, sollten Sie die MySQL-Eingabeaufforderung sehen:
mysql >
Hinweis
Wenn Sie MariaDB verwenden, sehen Sie möglicherweise stattdessen eine Eingabeaufforderung wie die folgende:
MariaDB [(none)]>
-
So erstellen Sie eine Beispieldatenbank mit dem Namen
test_db
, ausführen:CREATE DATABASE test_db;
Sie sollten diese Ausgabe sehen, die bestätigt, dass die Datenbank erfolgreich erstellt wurde:
Query OK, 1 row affected (0.01 sec)
-
Wechseln Sie zur
test_db
Datenbank:USE test_db;
Sie sollten diese Ausgabe sehen:
Database changed
-
Sie haben die
test_db
erstellt und es ausgewählt. Erstellen Sie als Nächstes eine Tabelle mit dem Namencustomers
:CREATE TABLE customers ( customer_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_name VARCHAR(50) ) ENGINE = InnoDB;
Sie sollten diese Ausgabe sehen:
Query OK, 0 rows affected (0.03 sec)
-
Fügen Sie den
customers
einige Datensätze hinzu Tisch. Führen Sie das folgendeINSERT
aus Befehle nacheinander:INSERT INTO customers(customer_name) VALUES ('JOHN PAUL'); INSERT INTO customers(customer_name) VALUES ('PETER DOE'); INSERT INTO customers(customer_name) VALUES ('MARY DOE'); INSERT INTO customers(customer_name) VALUES ('CHRISTINE JAMES'); INSERT INTO customers(customer_name) VALUES ('MARK WELL'); INSERT INTO customers(customer_name) VALUES ('FRANK BRIAN');
Diese Ausgabe wird nach dem Einfügen jedes Datensatzes angezeigt:
Query OK, 1 row affected (0.00 sec) ...
-
Überprüfen Sie, ob die Kundeninformationen in die Datenbank eingefügt wurden. Führen Sie dieses
SELECT
aus Befehl:SELECT * FROM customers;
Sie sollten diese Kundenliste sehen:
+-------------+-----------------+ | customer_id | customer_name | +-------------+-----------------+ | 1 | JOHN PAUL | | 2 | PETER DOE | | 3 | MARY DOE | | 4 | CHRISTINE JAMES | | 5 | MARK WELL | | 6 | FRANK BRIAN | +-------------+-----------------+ 6 rows in set (0.00 sec)
-
Erstellen Sie einen
sales
Tisch. Diese Tabelle verwendet die Spaltecustomer_id
um auf diecustomers
zu verweisen Tabelle:CREATE TABLE sales ( order_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_id BIGINT, sales_amount DECIMAL(17,2) ) ENGINE = InnoDB;
Diese Ausgabe erscheint:
Query OK, 0 rows affected (0.03 sec)
-
Füllen Sie als Nächstes die
sales
aus Tabelle mit einigen Aufzeichnungen. Führen Sie das folgendeINSERT
aus Befehle nacheinander:INSERT INTO sales (customer_id, sales_amount) VALUES ('1','25.75'); INSERT INTO sales (customer_id, sales_amount) VALUES ('2','85.25'); INSERT INTO sales (customer_id, sales_amount) VALUES ('5','3.25'); INSERT INTO sales (customer_id, sales_amount) VALUES ('4','200.75'); INSERT INTO sales (customer_id, sales_amount) VALUES ('5','88.10'); INSERT INTO sales (customer_id, sales_amount) VALUES ('1','100.00'); INSERT INTO sales (customer_id, sales_amount) VALUES ('2','45.00'); INSERT INTO sales (customer_id, sales_amount) VALUES ('4','15.80');
Diese Ausgabe wird nach dem Einfügen jedes Datensatzes angezeigt:
Query OK, 1 row affected (0.01 sec) ...
-
Überprüfen Sie die Daten in den
sales
Tisch. Führen Sie diesesSELECT
aus Befehl:SELECT * FROM sales;
Diese Liste mit Verkaufsdaten sollte jetzt angezeigt werden:
+----------+-------------+--------------+ | order_id | customer_id | sales_amount | +----------+-------------+--------------+ | 1 | 1 | 25.75 | | 2 | 2 | 85.25 | | 3 | 5 | 3.25 | | 4 | 4 | 200.75 | | 5 | 5 | 88.10 | | 6 | 1 | 100.00 | | 7 | 2 | 45.00 | | 8 | 4 | 15.80 | +----------+-------------+--------------+ 8 rows in set (0.00 sec)
Nachdem Sie die Datenbank und die zugehörigen Tabellen eingerichtet haben, können Sie nun die verschiedenen Unterabfragen in MySQL implementieren.
So verwenden Sie eine korrelierte Unterabfrage
Eine korrelierte Unterabfrage ist eine Art verschachtelte Abfrage, die die Werte einer übergeordneten Abfrage verwendet. Diese Arten von Abfragen verweisen mit einer Spalte auf die übergeordnete Abfrage. Die verschachtelte Abfrage wird einmal für jede Zeile in der übergeordneten Abfrage ausgeführt.
Das folgende Beispiel zeigt eine Abfrage, die alle Kunden auswählt. Innerhalb der Abfrage gibt es eine korrelierte Unterabfrage, die den Gesamtumsatzbetrag für jeden Kunden aus sales
abruft Tabelle.
-
Führen Sie die Beispielabfrage aus:
SELECT customer_id, customer_name, (SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id) as total_sales_amount FROM customers;
In diesem Beispiel lautet die Unterabfrage
SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id
, das in Klammern steht.Eine Liste der Gesamtumsätze der Kunden wird angezeigt:
+-------------+-----------------+--------------------+ | customer_id | customer_name | total_sales_amount | +-------------+-----------------+--------------------+ | 1 | JOHN PAUL | 125.75 | | 2 | PETER DOE | 130.25 | | 3 | MARY DOE | NULL | | 4 | CHRISTINE JAMES | 216.55 | | 5 | MARK WELL | 91.35 | | 6 | FRANK BRIAN | NULL | +-------------+-----------------+--------------------+ 6 rows in set (0.00 sec)
Die obige Ausgabe der korrelierten Unterabfrage kann Ihnen eine zusammengefasste Liste der Kundenbestellungen liefern. Bitte beachten, da
customer_id
s3
und6
haben keine zugeordneten Datensätze in der Verkaufstabelle, derentotal_sales_amount
istNULL
. -
Eine elegantere Art, diese Liste darzustellen, ist die Rückgabe von
0
stattNULL
für die Kunden mit null Umsatz. Umschließen Sie dazu die von der Unterabfrage generierte Ausgabe mit einemIFNULL(expression, 0)
Erklärung. Führen Sie diesen aktualisierten Befehl aus:SELECT customer_id, customer_name, IFNULL((SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id), 0) as total_sales_amount FROM customers;
Es erscheint die folgende Ausgabe. MySQL gibt 0,00 für alle Zeilen zurück, die sonst
NULL
zurückgegeben hätten Werte.+-------------+-----------------+--------------------+ | customer_id | customer_name | total_sales_amount | +-------------+-----------------+--------------------+ | 1 | JOHN PAUL | 125.75 | | 2 | PETER DOE | 130.25 | | 3 | MARY DOE | 0.00 | | 4 | CHRISTINE JAMES | 216.55 | | 5 | MARK WELL | 91.35 | | 6 | FRANK BRIAN | 0.00 | +-------------+-----------------+--------------------+ 6 rows in set (0.00 sec)
Dieser Ansatz trägt dazu bei, dass die Ausgabe keine weiteren Berechnungen in den Datensätzen beeinträchtigt.
So verwenden Sie eine korrelierte Unterabfrage in einem Vergleichsoperator
Unterabfragen sind nützlich, um Geschäftslogik in die Datenbankabfrageebene zu verschieben. Die folgenden geschäftlichen Anwendungsfälle weisen korrelierte Unterabfragen auf, die in der WHERE-Klausel einer übergeordneten Abfrage platziert werden:
-
Stellen Sie sich ein Szenario vor, in dem Sie eine Liste aller in der Datenbank registrierten Kunden erhalten möchten, denen keine Verkäufe zugeordnet sind. Sie können eine Unterabfrage zusammen mit dem MySQL-Vergleichsoperator
NOT IN
verwenden und diese Kunden abrufen:SELECT customer_id, customer_name FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);
In diesem Beispiel lautet die Unterabfrage
SELECT customer_id FROM sales
, die in Klammern steht. Der obige SQL-Befehl gibt eine Liste mit zwei Kunden aus, die nicht in der Verkaufstabelle gefunden werden:+-------------+---------------+ | customer_id | customer_name | +-------------+---------------+ | 3 | MARY DOE | | 6 | FRANK BRIAN | +-------------+---------------+ 2 rows in set (0.00 sec)
In einer Produktionsumgebung können Sie diese Art von Datensätzen verwenden, um bessere Geschäftsentscheidungen zu treffen. Sie können beispielsweise ein Skript mit einer anderen Sprache wie PHP oder Python erstellen, um diesen Kunden eine E-Mail zu senden und zu fragen, ob sie ein Problem bei der Bestellung haben.
-
Ein weiterer Anwendungsfall ist die Datenbereinigung. Beispielsweise können Sie eine Unterabfrage verwenden, um Kunden zu löschen, die noch nie eine Bestellung aufgegeben haben:
DELETE FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);
Der obige SQL-Befehl löscht die beiden Kunden und gibt Folgendes aus:
Query OK, 2 rows affected (0.01 sec)
Wenn Sie einen Befehl zum erneuten Auflisten aller Kunden ausführen, sollten diese Kunden nicht mehr in der Tabelle erscheinen:
SELECT * FROM customers;
Die folgende Ausgabe bestätigt, dass die Kunden ohne zugeordnete Bestellungen gelöscht wurden:
+-------------+-----------------+ | customer_id | customer_name | +-------------+-----------------+ | 1 | JOHN PAUL | | 2 | PETER DOE | | 4 | CHRISTINE JAMES | | 5 | MARK WELL | +-------------+-----------------+ 4 rows in set (0.00 sec)
So verwenden Sie eine Unterabfrage als abgeleitete Tabelle
Wenn Unterabfragen im FROM
verwendet werden -Klausel einer übergeordneten Abfrage, werden sie als abgeleitete Tabellen bezeichnet . Sie sind sehr wichtig, wenn komplexe Abfragen implementiert werden, die andernfalls eine MySQL VIEW
erfordern würden , JOIN
, oder UNION
Klausel. Eine abgeleitete Tabelle existiert in der Abfrage, die sie erstellt hat, und wird nicht dauerhaft in der Datenbank gespeichert.
Wenn Unterabfragen als abgeleitete Tabellen verwendet werden, isolieren sie die verschiedenen Teile der SQL-Anweisung. Mit anderen Worten, die Unterabfrage stellt einen vereinfachten Ausdruck einer Tabelle bereit, die im Rahmen der übergeordneten Abfrage verwendet werden kann.
Hinweis Denken Sie daran, dass jede abgeleitete Tabelle mit einem Alias versehen werden muss.
Führen Sie den folgenden Befehl aus, um eine abgeleitete Tabellenunterabfrage mit dem Alias order_summary
zu erstellen :
SELECT customer_id
FROM
(
SELECT
customer_id,
count(order_id) as total_orders
FROM sales
group by customer_id
) as order_summary
WHERE order_summary.total_orders > 1;
HinweisIn diesem Befehl erscheint die Unterabfrage in Klammern als:
SELECT customer_id, count(order_id) as total_orders FROM sales group by customer_id
Der obige Befehl fragt die Verkaufstabelle ab, um Kunden mit mehr als einer Bestellung zu ermitteln. Wenn Sie die Abfrage ausführen, wird diese Ausgabe angezeigt:
+-------------+
| customer_id |
+-------------+
| 1 |
| 2 |
| 5 |
| 4 |
+-------------+
4 rows in set (0.00 sec)
Die obige Liste zeigt vier customer_id
s, die mehr als eine Bestellung haben. Als Beispiel für einen geschäftlichen Anwendungsfall können Sie eine solche Abfrage in einem Skript verwenden, das Kunden bei ihrem nächsten Einkauf mit einem Bonus belohnt.
Weitere Informationen
Weitere Informationen zu diesem Thema finden Sie in den folgenden Ressourcen. Obwohl diese in der Hoffnung bereitgestellt werden, dass sie nützlich sind, beachten Sie bitte, dass wir nicht für die Genauigkeit oder Aktualität extern gehosteter Materialien garantieren können.
- MySQL-Unterabfragen