Una sottoquery è una query SQL (Structured Query Language) nidificata all'interno di un'altra query SQL. Il comando in cui è nidificata la sottoquery viene definito query padre. Le sottoquery vengono utilizzate per pre-elaborare i dati utilizzati nella query padre. Le sottoquery possono essere applicate in SELECT
, INSERT
, UPDATE
e DELETE
operazioni.
Quando vengono eseguite sottoquery, la sottoquery viene elaborata prima della query padre. Quando si creano applicazioni MySQL, l'utilizzo di sottoquery offre numerosi vantaggi:
- Rompono le istruzioni SQL in semplici unità logiche, che possono renderle più facili da comprendere e mantenere. In altre parole, le sottoquery aiutano a isolare parti complesse delle query.
- Eliminano la necessità di utilizzare
UNION
complessi dichiarazioni eJOIN
dichiarazioni. - Sono utilizzati per imporre l'integrità referenziale in uno scenario in cui le chiavi esterne non vengono implementate.
- Aiutano gli sviluppatori a codificare la logica aziendale nelle query MySQL.
In questa guida imparerai:
- Come utilizzare una sottoquery correlata
- Come utilizzare una sottoquery correlata in un operatore di confronto
- Come utilizzare una sottoquery come tabella derivata
Prima di iniziare
Per seguire questa guida, assicurati di avere quanto segue:
-
Se non l'hai già fatto, crea un account Linode e un'istanza di calcolo. Consulta le nostre guide Introduzione a Linode e Creazione di un'istanza di calcolo.
-
Segui la nostra guida alla configurazione e alla protezione di un'istanza di calcolo per aggiornare il tuo sistema. Potresti anche voler impostare il fuso orario, configurare il tuo nome host, creare un account utente limitato e rafforzare l'accesso SSH.
-
Il software del server MySQL (o MariaDB) installato sul tuo Linode. Fare riferimento alla sezione MySQL, che contiene guide che descrivono come installare MySQL su diverse distribuzioni Linux.
Configurazione del database
Per comprendere come funzionano le sottoquery, creare prima un database di esempio. Questo database di esempio viene utilizzato per eseguire le diverse query di esempio in questa guida:
-
SSH
sul tuo server e accedi a MySQL come root:mysql -u root -p
Quando richiesto, inserisci la password di root del tuo server MySQL e premi Invio continuare. Nota che la password di root del tuo server MySQL non è la stessa della password di root per il tuo Linode.
Nota
Se la tua password non viene accettata, potresti dover eseguire il comando precedente con
sudo
:sudo mysql -u root -p
-
Se la tua password viene accettata, dovresti vedere il prompt di MySQL:
mysql >
Nota
Se stai usando MariaDB, potresti invece visualizzare un messaggio come il seguente:
MariaDB [(none)]>
-
Per creare un database di esempio denominato
test_db
, esegui:CREATE DATABASE test_db;
Dovresti vedere questo output, che conferma che il database è stato creato correttamente:
Query OK, 1 row affected (0.01 sec)
-
Passa a
test_db
banca dati:USE test_db;
Dovresti vedere questo output:
Database changed
-
Hai creato il
test_db
e l'ho selezionato. Quindi, crea una tabella denominatacustomers
:CREATE TABLE customers ( customer_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_name VARCHAR(50) ) ENGINE = InnoDB;
Dovresti vedere questo output:
Query OK, 0 rows affected (0.03 sec)
-
Aggiungi alcuni record ai
customers
tavolo. Esegui il seguenteINSERT
comandi uno per uno: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');
Questo output viene mostrato dopo l'inserimento di ogni record:
Query OK, 1 row affected (0.00 sec) ...
-
Verificare che le informazioni sui clienti siano state inserite nel database. Esegui questo
SELECT
comando:SELECT * FROM customers;
Dovresti vedere questo elenco di clienti:
+-------------+-----------------+ | 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)
-
Crea un
sales
tavolo. Questa tabella utilizza la colonnacustomer_id
per fare riferimento aicustomers
tabella:CREATE TABLE sales ( order_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_id BIGINT, sales_amount DECIMAL(17,2) ) ENGINE = InnoDB;
Viene visualizzato questo output:
Query OK, 0 rows affected (0.03 sec)
-
Quindi, compila le
sales
tabella con alcuni record. Esegui il seguenteINSERT
comandi uno per uno: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');
Questo output viene mostrato dopo l'inserimento di ogni record:
Query OK, 1 row affected (0.01 sec) ...
-
Verifica i dati nelle
sales
tavolo. Esegui questoSELECT
comando:SELECT * FROM sales;
Questo elenco di dati di vendita dovrebbe ora essere mostrato:
+----------+-------------+--------------+ | 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)
Dopo aver impostato il database e le relative tabelle, ora puoi implementare le diverse sottoquery in MySQL.
Come utilizzare una sottoquery correlata
Una sottoquery correlata è un tipo di query nidificata che utilizza i valori di una query padre. Questi tipi di query fanno riferimento alla query padre con una colonna. La query nidificata viene eseguita una volta per ogni riga nella query padre.
L'esempio seguente presenta una query che seleziona tutti i clienti. All'interno della query è presente una sottoquery correlata che recupera l'importo totale delle vendite per ciascun cliente dalle sales
tabella.
-
Esegui la query di esempio:
SELECT customer_id, customer_name, (SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id) as total_sales_amount FROM customers;
In questo esempio, la sottoquery è
SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id
, che appare tra parentesi.Viene visualizzato un elenco delle vendite totali effettuate dai clienti:
+-------------+-----------------+--------------------+ | 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)
L'output sopra della subquery correlata è in grado di fornire un elenco riepilogativo degli ordini dei clienti. Nota, poiché
customer_id
s3
e6
non hanno record associati nella tabella delle vendite, il lorototal_sales_amount
èNULL
. -
Un modo più elegante per presentare questo elenco è restituire
0
invece diNULL
per i clienti con zero vendite. Per fare ciò, racchiudere l'output generato dalla sottoquery con unIFNULL(expression, 0)
dichiarazione. Esegui questo comando aggiornato: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;
Viene visualizzato il seguente output. MySQL restituisce 0.00 per tutte le righe che altrimenti avrebbero restituito
NULL
valori.+-------------+-----------------+--------------------+ | 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)
Questo approccio aiuta a garantire che l'output non danneggi ulteriori calcoli sui record.
Come utilizzare una sottoquery correlata in un operatore di confronto
Le sottoquery sono utili per spostare la logica aziendale nel livello di query del database. I seguenti casi d'uso aziendali presentano sottoquery correlate poste all'interno della clausola WHERE di una query principale:
-
Considera uno scenario in cui desideri ottenere un elenco di tutti i clienti registrati nel database che non hanno vendite associate. Puoi usare una sottoquery insieme all'operatore di confronto MySQL
NOT IN
e recuperare questi clienti:SELECT customer_id, customer_name FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);
In questo esempio, la sottoquery è
SELECT customer_id FROM sales
, che appare tra parentesi. Il comando SQL precedente restituisce un elenco di due clienti che non si trovano nella tabella delle vendite:+-------------+---------------+ | customer_id | customer_name | +-------------+---------------+ | 3 | MARY DOE | | 6 | FRANK BRIAN | +-------------+---------------+ 2 rows in set (0.00 sec)
In un ambiente di produzione, è possibile utilizzare questo tipo di recordset per prendere decisioni aziendali migliori. Ad esempio, puoi creare uno script utilizzando un altro linguaggio come PHP o Python per inviare un'e-mail a questi clienti e chiedere se hanno problemi a effettuare un ordine.
-
Un altro caso d'uso è nella pulizia dei dati. Ad esempio, puoi utilizzare una sottoquery per eliminare i clienti che non hanno mai effettuato un ordine:
DELETE FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);
Il comando SQL precedente elimina i due clienti e restituisce quanto segue:
Query OK, 2 rows affected (0.01 sec)
Se esegui un comando per elencare nuovamente tutti i clienti, questi clienti non dovrebbero più essere visualizzati nella tabella:
SELECT * FROM customers;
L'output seguente conferma che i clienti senza ordini associati sono stati eliminati:
+-------------+-----------------+ | customer_id | customer_name | +-------------+-----------------+ | 1 | JOHN PAUL | | 2 | PETER DOE | | 4 | CHRISTINE JAMES | | 5 | MARK WELL | +-------------+-----------------+ 4 rows in set (0.00 sec)
Come utilizzare una sottoquery come tabella derivata
Quando le sottoquery vengono utilizzate nel FROM
clausola di una query padre, sono denominate tabelle derivate . Sono molto importanti quando si implementano query complesse che altrimenti richiederebbero una VIEW
MySQL , JOIN
o UNION
clausola. Una tabella derivata esiste nella query che l'ha creata e non viene salvata in modo permanente nel database.
Quando le sottoquery vengono utilizzate come tabelle derivate, isolano le diverse parti dell'istruzione SQL. In altre parole, la sottoquery fornisce un'espressione semplificata di una tabella che può essere utilizzata nell'ambito della query padre.
Nota Ricorda, ogni tabella derivata deve avere un alias.
Esegui il comando seguente per creare una sottoquery di tabella derivata con alias order_summary
:
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;
NotaIn questo comando, la sottoquery appare tra parentesi come:
SELECT customer_id, count(order_id) as total_orders FROM sales group by customer_id
Il comando precedente interroga la tabella delle vendite per determinare i clienti con più di 1 ordine. Quando esegui la query, viene visualizzato questo output:
+-------------+
| customer_id |
+-------------+
| 1 |
| 2 |
| 5 |
| 4 |
+-------------+
4 rows in set (0.00 sec)
L'elenco sopra mostra quattro customer_id
s che hanno più di un ordine. Come esempio di caso d'uso aziendale, puoi utilizzare tale query in uno script che premia i clienti con un bonus al loro prossimo acquisto.
Maggiori informazioni
Si consiglia di consultare le seguenti risorse per ulteriori informazioni su questo argomento. Sebbene questi siano forniti nella speranza che possano essere utili, tieni presente che non possiamo garantire l'accuratezza o la tempestività dei materiali ospitati esternamente.
- Sottoquery MySQL