14th May 2024 Tempo di lettura: 13 minuti 10 esercizi sulle subquery correlate con soluzioni LearnSQL.it Team sql sottoquery pratica su sql Indice Esercizi su un database Store Esercizio 1: Prodotti costosi in ogni categoria Esercizio 2: Il numero di prodotti costosi in ogni categoria Esercizio 3: Prodotti fuori produzione, continuati e tutti i prodotti di una categoria Altre tabelle nel database del negozio: Tabelle Clienti e Acquisti Esercizio 4: Prodotti in categorie Esercizio 5: Percentuale di denaro speso dal cliente per l'acquisto Esercizio 6: Clienti con acquisti superiori alla loro spesa media Esercizi sul modello di dati dell'università Esercizio 7: Studenti con voti superiori alla media Esercizio 8: Numero di studenti con lo stesso voto o superiore Esercizio 9: Studenti promossi e non promossi Esercizio 10: Ancora medie Conclusioni e passi successivi Le subquery correlate sono una potente funzione SQL essenziale per l'analisi avanzata dei dati. Questo articolo fornisce 10 esercizi pratici per aiutarvi a padroneggiare le subquery correlate. L'SQL è un'abilità fondamentale per chiunque lavori con i dati, sia che si tratti di un analista di dati, di uno sviluppatore SQL, di un ingegnere dei dati o di qualsiasi altra professione correlata. La padronanza di SQL non si limita alla semplice comprensione delle nozioni di base. È necessario anche imparare funzioni SQL avanzate, come le subquery. Una subquery è una query SQL annidata all'interno di una query più grande. Esistono diversi tipi di subquery. Una subquery correlata è un tipo di subquery che fa riferimento alla query esterna e non può essere eseguita in modo indipendente. Le subquery, e in particolare le subquery correlate, possono essere un argomento impegnativo per gli studenti di SQL. In precedenza, abbiamo fornito una raccolta di esercizi sulle subquery nel nostro articolo: Esercitazioni sulle subquery SQL: 15 esercizi con soluzioni. In questo articolo vogliamo fornirvi una serie di esercizi pratici specifici sull'argomento delle subquery correlate. Gli esercizi di questo articolo sono tratti dai nostri corsi interattivi Basic SQL Practice: A Store e SQL Practice: University. Entrambi i corsi fanno parte del percorso "Pratica su SQL", che offre diversi corsi di pratica di SQL. Tutti i corsi della traccia si basano su scenari reali e sono organizzati per argomenti SQL, per aiutarvi a concentrarvi sulla vostra area di interesse. Esercizi su un database Store La prima serie di esercizi si basa sul database di un negozio online. Questi esercizi sono tratti dal nostro corso Basic SQL Practice: A Store. Inizieremo in piccolo e lavoreremo con due sole tabelle: product e category. La tabella product contiene un elenco di prodotti disponibili nel negozio. product_id - l'ID del prodotto product_name - il nome del prodotto category_id - l'ID della categoria del prodotto. Aiuta a connettersi con la tabella delle categorie. quantity_per_unit - la quantità di articoli del prodotto in un'unità. unit_price - il prezzo del prodotto discontinued - l'informazione se il prodotto è ancora disponibile nel negozio (valore FALSO) o se è stato dismesso (VERO). La tabella category contiene informazioni sulle categorie dei prodotti: category_id - l'ID della categoria name - il nome della categoria description - la descrizione opzionale della categoria Esercizio 1: Prodotti costosi in ogni categoria Esercizio: Trovare i prodotti che sono più costosi del prezzo medio dei prodotti della propria categoria. Includere nel risultato il nome della categoria, il nome del prodotto e il prezzo unitario. Soluzione: SELECT c.name, p.product_name, p.unit_price FROM category AS c JOIN product AS p ON c.category_id = p.category_id WHERE p.unit_price > ( SELECT AVG(unit_price) FROM product JOIN category ON product.category_id = category.category_id WHERE category.category_id = c.category_id ); Spiegazione della soluzione: Nella soluzione, si utilizza una sottoquery correlata per calcolare il prezzo unitario medio dei prodotti appartenenti alla stessa categoria del prodotto elaborato dalla query esterna. Questa sottoquery fa riferimento alla categoria, indicata come c, dalla query esterna. Identifica i prodotti di questa categoria e calcola il loro prezzo medio. I prodotti che costano più della media della categoria vengono filtrati in base a questa media. La query esterna recupera e visualizza il nome della categoria, il nome del prodotto e il prezzo unitario di questi prodotti. Esercizio 2: Il numero di prodotti costosi in ogni categoria Esercizio: Mostrare i nomi delle categorie e il numero di prodotti di questa categoria con un prezzo unitario superiore al prezzo medio di un prodotto di questa categoria. Mostrare solo le categorie che hanno tali prodotti. Visualizzare due colonne: name (il nome della categoria) e expensive_products (il numero di prodotti che costano più del prodotto medio di questa categoria). Soluzione: SELECT c.name, COUNT(*) AS expensive_products FROM category AS c JOIN product AS p ON c.category_id = p.category_id WHERE p.unit_price > ( SELECT AVG(unit_price) FROM product JOIN category ON product.category_id = category.category_id WHERE category.category_id = c.category_id ) GROUP BY c.category_id, c.name; Spiegazione della soluzione: Questo esercizio è simile al precedente. Anche in questo caso dobbiamo trovare i prodotti con un prezzo unitario superiore al prezzo medio della categoria. Tuttavia, questa volta vogliamo contare i prodotti di ogni categoria. Nella soluzione, utilizziamo la stessa sottoquery correlata di prima: calcoliamo il prezzo unitario medio dei prodotti della stessa categoria del prodotto elaborato dalla query esterna. Questa media viene poi utilizzata nella query principale per filtrare solo i prodotti il cui prezzo unitario è superiore alla media della categoria. La query principale conta questi prodotti utilizzando COUNT(*) e raggruppa i risultati per categoria con GROUP BY. Il risultato finale mostra il nome della categoria e il numero di prodotti. Esercizio 3: Prodotti fuori produzione, continuati e tutti i prodotti di una categoria Esercizio: Per ogni categoria, visualizzare il suo name, il numero di prodotti interrotti in questa categoria (discontinued_products), il numero di prodotti continuati in questa categoria (continued_products) e il numero di tutti i prodotti in questa categoria (all_products). Soluzione: SELECT c.name, (SELECT COUNT(*) FROM product WHERE category_id = c.category_id AND discontinued IS TRUE) AS discontinued_products, (SELECT COUNT(*) FROM product WHERE category_id = c.category_id AND discontinued IS FALSE) AS continued_products, (SELECT COUNT(*) FROM product WHERE category_id = c.category_id) AS all_products FROM category c; Spiegazione della soluzione: Qui si utilizzano tre sottoquery correlate nell'istruzione SELECT per ottenere il conteggio dei prodotti in base al loro stato di continuazione/discontinuazione per ogni categoria. Ogni sottoquery si correla con la query principale attraverso l'istruzione category_id in modo che i conteggi siano corretti per ogni categoria. La prima sottoquery conta il numero di prodotti in una categoria in cui il flag discontinued è TRUE. In questo modo si ottiene un conteggio totale di tutti i prodotti non più disponibili per ogni categoria. La seconda subquery conta il numero di prodotti ancora attivi in ogni categoria, utilizzando un metodo simile. La terza sottoquery conta semplicemente il numero di tutti i prodotti di una categoria. In alternativa, questo esercizio potrebbe essere risolto senza subquery, utilizzando una combinazione di CASE WHEN con SUM e GROUP BY. Come esercizio alternativo: potete risolvere questo esercizio in entrambi i modi? Altre tabelle nel database del negozio: Tabelle Clienti e Acquisti Nei prossimi esercizi lavoreremo con altre tabelle del database del negozio relative agli acquisti: customer, purchase, e purchase_item. La tabella customer contiene le informazioni sui clienti. Ha le seguenti colonne: customer_id - l'ID del cliente. contact_name - il nome completo del cliente contact_email - l'e-mail del cliente. La tabella purchase contiene le informazioni su ciascun ordine: purchase_id - l'ID dell'acquisto. customer_id - l'ID del cliente. total_price - il prezzo totale dell'ordine. purchase_date - il timestamp dell'acquisto. La tabella purchase_item collega gli acquisti con i prodotti. La tabella contiene le seguenti colonne purchase_id - l'ID dell'acquisto. product_id - l'ID del prodotto acquistato. unit_price - il prezzo di un'unità di prodotto. quantity - il numero di unità acquistate di un prodotto. Esercizio 4: Prodotti in categorie Esercizio: Per ogni prodotto acquistato, visualizzare il nome del prodotto, la quantità massima in cui è stato acquistato e il numero di acquisti (di questo prodotto in questa quantità massima). Visualizzare tre colonne: product_name, quantity, e purchases_number. Soluzione: SELECT product_name, quantity, COUNT(purchase_id) AS purchases_number FROM purchase_item pi JOIN product p ON pi.product_id = p.product_id WHERE quantity = (SELECT MAX(quantity) FROM purchase_item WHERE product_id = pi.product_id) GROUP BY pi.product_id, product_name, quantity; Spiegazione della soluzione: Vogliamo trovare la quantità massima in cui ogni prodotto è stato acquistato e il numero di acquisti effettuati. Per ottenere questo risultato utilizziamo una subquery correlata e GROUP BY. Per prima cosa, utilizziamo una sottoquery correlata in WHERE per determinare la quantità massima in cui ogni prodotto è stato acquistato. Poi, nella query esterna, utilizziamo questo valore per trovare gli acquisti in cui la quantità è uguale alla quantità massima. Infine, la query esterna raggruppa i risultati per product_id, product_name e quantity e utilizza la funzione aggregata COUNT(purchase_id) per calcolare il numero di acquisti per ciascun prodotto alla quantità massima. Esercizio 5: Percentuale di denaro speso dal cliente per l'acquisto Esercizio: Per ogni cliente che ha effettuato un qualsiasi acquisto, visualizzare l'ID di ogni acquisto effettuato da questo cliente, la percentuale del denaro speso per quell'acquisto rispetto a tutto il denaro speso da quel cliente. Arrotondare le percentuali a numeri interi. Mostrare tre colonne: contact_name, purchase_id e percentage. Soluzione: SELECT contact_name, purchase_id, ROUND(total_price * 100.0 / (SELECT SUM(total_price) FROM purchase WHERE customer_id = p.customer_id)) AS percentage FROM purchase p JOIN customer ON p.customer_id = customer.customer_id; Spiegazione della soluzione: Nella query esterna elenchiamo ogni acquisto effettuato da ciascun cliente. Uniamo le tabelle purchase e customer per visualizzare il nome del contatto del cliente e l'ID dell'acquisto. Utilizziamo una sottoquery correlata per scoprire l'importo totale speso dal cliente corrente. Utilizziamo l'importo trovato dalla sottoquery per calcolare la percentuale della spesa totale che rappresenta l'acquisto corrente. Esercizio 6: Clienti con acquisti superiori alla loro spesa media Esercizio: Trovare i clienti il cui ultimo acquisto è stato superiore all'importo medio. Visualizzare il nome del cliente e il totale dell'ultimo acquisto. Soluzione: SELECT c.contact_name, p.total_price AS last_purchase_total FROM purchase p JOIN customer c ON p.customer_id = c.customer_id WHERE p.purchase_date = ( SELECT MAX(lp.purchase_date) FROM purchase lp WHERE lp.customer_id = p.customer_id ) AND p.total_price > ( SELECT AVG(ap.total_price) FROM purchase ap WHERE ap.customer_id = p.customer_id ); Spiegazione della soluzione: Questo esercizio richiede due sottoquery. La prima subquery viene utilizzata per trovare la data dell'ultimo acquisto di ciascun cliente, in modo simile alla subquery dell'Esercizio 4, ma concentrandosi sulla data della transazione anziché sulle quantità. La seconda subquery calcola il prezzo totale medio degli acquisti del cliente e viene utilizzata per filtrare gli acquisti il cui prezzo è superiore alla media. Entrambe le sottoquery sono combinate nella clausola WHERE utilizzando l'operatore AND. Esercizi sul modello di dati dell'università La seconda serie di esercizi di questo articolo si basa sul database di un'università. Questi esercizi sono tratti dal nostro corso di SQL Practice: University. Il database dell'università ha 4 tabelle. La tabella course contiene informazioni sui corsi offerti dall'università e sui percorsi di apprendimento a cui sono associati: id - Un ID univoco per ogni corso. title - Il nome del corso. lecture_hours - Numero totale di ore di lezione del corso. tutorial_hours - Il numero totale di ore di lezione del corso. La tabella student contiene tutte le informazioni su ogni studente dell'università: id - Un ID univoco per ogni studente. first_name - Il nome dello studente. last_name - Il cognome dello studente. La tabella course_edition contiene informazioni su quali docenti insegnano ogni corso in ogni semestre: id - L'ID dell'edizione del corso. course_id - L'ID del corso. academic_semester - L'anno solare e il trimestre (autunno o primavera) del semestre. lecturer - il nome del docente che tiene il corso. La tabella course_enrollment contiene le informazioni relative agli studenti iscritti a un'edizione del corso: course_edition_id - L'ID dell'edizione del corso. student_id - l'ID dello studente. midterm_grade - Il voto intermedio ricevuto dallo studente. final_grade - Il voto finale ricevuto dallo studente. course_letter_grade - Il voto del corso, sotto forma di lettera (A+, A, A-, B+, B, B-, C+, C, C-, D+, D, D- o F). passed - Se lo studente ha superato (TRUE) o non superato (FALSE) il corso. Se uno studente non ha ancora sostenuto l'esame, nella tabella possono essere presenti alcuni campi NULL. Esercizio 7: Studenti con voti superiori alla media Esercizio: Trovare gli studenti che hanno ottenuto un voto finale superiore alla media in una qualsiasi delle edizioni del corso che hanno frequentato. Mostrare: nome e cognome dello studente, titolo del corso e final_grade. Mostrare solo gli studenti il cui voto finale in questa edizione del corso è stato superiore alla media dei voti finali in questa edizione del corso. Soluzione: SELECT first_name, last_name, title, final_grade FROM course_enrollment AS c_en JOIN student AS s ON c_en.student_id = s.id JOIN course_edition AS c_ed ON c_en.course_edition_id = c_ed.id JOIN course AS c ON c_ed.course_id = c.id WHERE final_grade > ( SELECT AVG(final_grade) FROM course_enrollment AS c_e WHERE c_e.course_edition_id = c_en.course_edition_id ); Spiegazione della soluzione: La soluzione utilizza una singola query correlata. Nella sottoquery correlata si trova la media dei voti finali per l'edizione del corso elaborata nella query principale. Utilizziamo quindi la media trovata nella sottoquery per filtrare le iscrizioni ai corsi in cui il voto finale dello studente era superiore alla media. Nella query principale uniamo le tabelle course_enrollment, student, course_edition e course per combinare il nome e il cognome dello studente con il titolo del corso e il voto ricevuto. Esercizio 8: Numero di studenti con lo stesso voto o superiore Esercizio:Per ogni voto finale nella tabella course_enrollment, contare il numero di studenti che hanno ottenuto esattamente quel voto o un voto superiore. Mostrare due colonne: final_grade e students_number. Soluzione: SELECT DISTINCT final_grade, (SELECT COUNT (student_id) FROM course_enrollment WHERE final_grade >= c.final_grade) AS students_number FROM course_enrollment c; Spiegazione della soluzione: La query principale seleziona ogni voto finale unico (distinto) dalla tabella course_enrollment. Per ognuno di questi voti, la sottoquery correlata conta il numero di studenti il cui voto finale è uguale o superiore al voto elaborato dalla query esterna. Il risultato viene visualizzato in due colonne: final_grade students_number , che indica il numero di studenti che hanno ottenuto quel voto o un voto superiore. Esercizio 9: Studenti promossi e non promossi Esercizio: Dividere gli studenti di ogni edizione del corso in due gruppi: quelli che hanno superato il corso e quelli che non l'hanno superato. Per ogni gruppo, visualizzare le seguenti colonne: course_edition_id passed average_final_grade - La media degli studenti di questo gruppo (promossi o non promossi), arrotondata al secondo decimale. average_edition_grade - La media complessiva degli studenti di questa edizione del corso, arrotondata al secondo decimale. Soluzione: SELECT course_edition_id, passed, ROUND(AVG(final_grade), 2) AS average_final_grade, (SELECT ROUND(AVG(final_grade), 2) FROM course_enrollment WHERE course_edition_id = c_e.course_edition_id) AS average_edition_grade FROM course_enrollment c_e GROUP BY course_edition_id, passed; Spiegazione della soluzione: La query esterna seleziona l'ID dell'edizione del corso, il valore di passed e la media dei voti finali per questo gruppo di studenti ("superato" o "non superato") usando la clausola regolare GROUP BY. Utilizza anche una sottoquery correlata per trovare il voto finale medio complessivo per l'edizione del corso elaborata nella query esterna e aggiunge questa media al risultato della query. In questo modo, è possibile confrontare il voto finale di ciascun gruppo con la media generale. Esercizio 10: Ancora medie Esercizio: Per ogni edizione del corso, mostrate i seguenti dati: title average_result - La media dei voti finali degli studenti con un voto finale superiore alla media dell'edizione del corso. Arrotondare il risultato a 0 decimali (cioè a un numero intero). results_better_than_average - Il numero di studenti il cui voto finale è superiore al voto finale medio dell'edizione del corso. Soluzione: SELECT c.title, ROUND(AVG(final_grade)) AS average_result, COUNT (student_id) AS results_better_than_average FROM course_enrollment AS c_en JOIN course_edition AS c_ed ON c_en.course_edition_id = c_ed.id JOIN course AS c ON c_ed.course_id = c.id WHERE final_grade > ( SELECT AVG(final_grade) FROM course_enrollment AS c_en2 WHERE c_en2.course_edition_id = c_en.course_edition_id ) GROUP BY c.id, c.title; Spiegazione della soluzione: Nella sottoquery correlata calcoliamo il voto finale medio per l'edizione del corso elaborata dalla query esterna. Utilizziamo questo valore per filtrare gli studenti il cui voto finale in questa edizione del corso è superiore alla media. Nella query esterna visualizziamo il titolo del corso, il numero di studenti con voto finale superiore alla media e il voto finale medio per questo gruppo di studenti. Conclusioni e passi successivi In questo articolo abbiamo esplorato diversi esercizi di subquery correlate per migliorare la comprensione di questa importante funzione di SQL. Per coloro che desiderano sviluppare ulteriormente le proprie competenze in SQL, consigliamo il nostro percorso "Pratica su SQL". Include 10 diversi corsi pratici di SQL. Ogni corso è ricco di esercizi pratici basati su scenari reali ed è organizzato in base agli argomenti di SQL, per aiutarvi a concentrarvi sulla vostra area di interesse. Inoltre, vi consigliamo di dare un'occhiata al nostro pacchetto Completo per sempre SQL - l'offerta definitiva per gli studenti di SQL. Questa offerta, che prevede un pagamento unico, fornisce l'accesso a vita a tutti i corsi attuali e futuri del nostro catalogo, compreso tutto ciò che fa parte del percorso "Pratica su SQL". È una risorsa inestimabile per chiunque voglia diventare un esperto di SQL. Tags: sql sottoquery pratica su sql