Esercizi SQL
Esercizio 1
Sezione intitolata “Esercizio 1”Dalla tabella clienti, mostrare tutte le colonne di tutte le righe.
Soluzione spiegata
In questo primo esercizio basta leggere l’intera tabella con SELECT *.
SELECT *FROM clienti;La query non filtra nulla e chiede al database di restituire tutti i dati presenti in clienti.
Esercizio 2
Sezione intitolata “Esercizio 2”Dalla tabella clienti (id, nome, email), mostrare solo nome ed email.
Soluzione spiegata
Qui non usiamo *, ma indichiamo solo le colonne che ci servono.
SELECT nome, emailFROM clienti;Il risultato contiene solo i dati utili alla richiesta e resta piu facile da leggere.
Esercizio 3
Sezione intitolata “Esercizio 3”Dalla tabella prodotti (id, nome, prezzo), mostrare nome con l’alias prodotto e prezzo con l’alias costo.
Soluzione spiegata
Gli alias aiutano a rendere il risultato piu chiaro senza cambiare i dati.
SELECT nome AS prodotto, prezzo AS costoFROM prodotti;AS assegna un nome temporaneo alle colonne nel risultato finale.
Esercizio 4
Sezione intitolata “Esercizio 4”Dalla tabella clienti (id, nome, citta), mostrare i clienti che hanno Roma nella colonna citta.
Soluzione spiegata
Usiamo WHERE per tenere solo le righe che rispettano la condizione.
SELECT id, nome, cittaFROM clientiWHERE citta = 'Roma';La query controlla la colonna citta riga per riga e tiene solo i clienti di Roma.
Esercizio 5
Sezione intitolata “Esercizio 5”Dalla tabella ordini (id, totale), mostrare gli ordini con totale maggiore di 100.
Soluzione spiegata
In questo caso il filtro riguarda un numero, quindi non usiamo apici.
SELECT id, totaleFROM ordiniWHERE totale > 100;Restano nel risultato solo le righe in cui totale supera 100.
Esercizio 6
Sezione intitolata “Esercizio 6”Dalla tabella prodotti (nome, prezzo), mostrare i prodotti con prezzo minore o uguale a 20.
Soluzione spiegata
L’operatore <= serve quando vuoi includere anche il valore di confine.
SELECT nome, prezzoFROM prodottiWHERE prezzo <= 20;La query mostra i prodotti economici, compresi quelli che costano esattamente 20.
Esercizio 7
Sezione intitolata “Esercizio 7”Dalla tabella clienti (nome, citta, attivo), mostrare i clienti di Roma che risultano attivi.
Soluzione spiegata
Con AND chiediamo che entrambe le condizioni siano vere.
SELECT nome, citta, attivoFROM clientiWHERE citta = 'Roma' AND attivo = TRUE;La riga entra nel risultato solo se il cliente e sia di Roma sia attivo.
Esercizio 8
Sezione intitolata “Esercizio 8”Dalla tabella clienti (nome, citta), mostrare i clienti che vivono a Roma oppure a Milano.
Soluzione spiegata
Con OR basta che almeno una delle due condizioni sia vera.
SELECT nome, cittaFROM clientiWHERE citta = 'Roma' OR citta = 'Milano';La query raccoglie i clienti di entrambe le citta in un unico risultato.
Esercizio 9
Sezione intitolata “Esercizio 9”Dalla tabella clienti (nome, attivo), mostrare i clienti che non sono attivi.
Soluzione spiegata
NOT ribalta la condizione che segue.
SELECT nome, attivoFROM clientiWHERE NOT attivo;Il risultato contiene solo le righe in cui attivo non risulta vero.
Esercizio 10
Sezione intitolata “Esercizio 10”Dalla tabella clienti (id, nome), mostrare i nomi in ordine alfabetico crescente.
Soluzione spiegata
Per ordinare i risultati usiamo ORDER BY con ASC.
SELECT id, nomeFROM clientiORDER BY nome ASC;ASC ordina dal valore piu piccolo al piu grande, quindi nel caso dei testi in ordine alfabetico.
Esercizio 11
Sezione intitolata “Esercizio 11”Dalla tabella prodotti (nome, prezzo), mostrare i prodotti dal prezzo piu alto al piu basso.
Soluzione spiegata
Per avere prima i valori piu grandi usiamo DESC.
SELECT nome, prezzoFROM prodottiORDER BY prezzo DESC;La query e utile quando vuoi vedere subito gli elementi piu costosi.
Esercizio 12
Sezione intitolata “Esercizio 12”Dalla tabella ordini (id, data_ordine), mostrare solo le prime 5 righe del risultato.
Soluzione spiegata
LIMIT restringe il numero di righe restituite.
SELECT id, data_ordineFROM ordiniLIMIT 5;Il database interrompe il risultato dopo cinque righe.
Esercizio 13
Sezione intitolata “Esercizio 13”Dalla tabella ordini (id, data_ordine), saltare le prime 5 righe e mostrare le successive 5.
Soluzione spiegata
Qui combiniamo LIMIT e OFFSET.
SELECT id, data_ordineFROM ordiniLIMIT 5 OFFSET 5;OFFSET 5 salta le prime cinque righe del risultato, poi LIMIT 5 ne prende altre cinque.
Esercizio 14
Sezione intitolata “Esercizio 14”Dalla tabella clienti (nome, email), mostrare i clienti che non hanno email salvata.
Soluzione spiegata
Con NULL non si usa =, ma IS NULL.
SELECT nome, emailFROM clientiWHERE email IS NULL;La query cerca proprio l’assenza del dato, non un testo vuoto.
Esercizio 15
Sezione intitolata “Esercizio 15”Dalla tabella clienti (nome, email), mostrare i clienti che hanno un’email presente.
Soluzione spiegata
Il contrario di IS NULL e IS NOT NULL.
SELECT nome, emailFROM clientiWHERE email IS NOT NULL;Restano solo le righe in cui la colonna email contiene un valore.
Esercizio 16
Sezione intitolata “Esercizio 16”Nella tabella clienti (id, nome, email), inserire un nuovo cliente con nome Luca ed email luca@email.it.
Soluzione spiegata
Con INSERT INTO aggiungiamo una nuova riga indicando chiaramente le colonne.
INSERT INTO clienti (nome, email)VALUES ('Luca', 'luca@email.it');Il primo valore va nella colonna nome, il secondo nella colonna email.
Esercizio 17
Sezione intitolata “Esercizio 17”Nella tabella prodotti (nome, prezzo), inserire due righe: Mouse a 19.90 e Tastiera a 49.90.
Soluzione spiegata
Un solo INSERT puo aggiungere piu righe.
INSERT INTO prodotti (nome, prezzo)VALUES ('Mouse', 19.90), ('Tastiera', 49.90);Ogni gruppo di valori tra parentesi crea una riga nuova nella tabella.
Esercizio 18
Sezione intitolata “Esercizio 18”Nella tabella clienti, aggiornare la citta del cliente con id = 3 impostandola a Bologna.
Soluzione spiegata
UPDATE modifica una riga esistente, mentre WHERE sceglie quale.
UPDATE clientiSET citta = 'Bologna'WHERE id = 3;Senza WHERE, la query modificherebbe la citta di tutte le righe.
Esercizio 19
Sezione intitolata “Esercizio 19”Nella tabella prodotti, aumentare del 10% il prezzo del prodotto con id = 5.
Soluzione spiegata
Il nuovo valore puo dipendere da quello gia presente nella colonna.
UPDATE prodottiSET prezzo = prezzo * 1.10WHERE id = 5;La formula prende il prezzo attuale e lo moltiplica per 1.10.
Esercizio 20
Sezione intitolata “Esercizio 20”Nella tabella clienti, eliminare la riga con id = 8.
Soluzione spiegata
Per cancellare una sola riga usiamo DELETE con un filtro preciso.
DELETE FROM clientiWHERE id = 8;Il filtro evita di cancellare piu righe del necessario.
Esercizio 21
Sezione intitolata “Esercizio 21”Dalla tabella ordini, contare quante righe ci sono.
Soluzione spiegata
COUNT(*) restituisce il numero totale di righe.
SELECT COUNT(*) AS numero_ordiniFROM ordini;L’alias rende piu leggibile il nome della colonna nel risultato.
Esercizio 22
Sezione intitolata “Esercizio 22”Dalla tabella ordini (totale), calcolare la somma di tutti i totali.
Soluzione spiegata
Per sommare molti valori numerici usiamo SUM().
SELECT SUM(totale) AS incasso_totaleFROM ordini;La query restituisce un solo valore riassuntivo con l’incasso complessivo.
Esercizio 23
Sezione intitolata “Esercizio 23”Dalla tabella prodotti (prezzo), calcolare il prezzo medio.
Soluzione spiegata
AVG() e la funzione che calcola la media aritmetica.
SELECT AVG(prezzo) AS prezzo_medioFROM prodotti;Il risultato e un solo numero che rappresenta il prezzo medio dei prodotti.
Esercizio 24
Sezione intitolata “Esercizio 24”Dalla tabella prodotti (prezzo), trovare il prezzo piu basso e il prezzo piu alto.
Soluzione spiegata
MIN() trova il valore piu piccolo, mentre MAX() trova il piu grande.
SELECT MIN(prezzo) AS prezzo_minimo, MAX(prezzo) AS prezzo_massimoFROM prodotti;In una sola query otteniamo entrambi gli estremi del catalogo.
Esercizio 25
Sezione intitolata “Esercizio 25”Dalla tabella clienti (citta), contare quanti clienti ci sono per ogni citta.
Soluzione spiegata
Con GROUP BY creiamo un gruppo per ogni citta, poi COUNT(*) conta le righe del gruppo.
SELECT citta, COUNT(*) AS numero_clientiFROM clientiGROUP BY citta;La query restituisce una riga per ogni citta presente nella tabella.
Esercizio 26
Sezione intitolata “Esercizio 26”Dalla tabella ordini (cliente_id, totale), calcolare il totale speso da ogni cliente.
Soluzione spiegata
Qui raggruppiamo per cliente e sommiamo il totale degli ordini del gruppo.
SELECT cliente_id, SUM(totale) AS totale_spesoFROM ordiniGROUP BY cliente_id;Ogni riga del risultato rappresenta un cliente con la somma dei suoi ordini.
Esercizio 27
Sezione intitolata “Esercizio 27”Dalla tabella ordini (cliente_id, totale), mostrare solo i clienti che hanno almeno 2 ordini.
Soluzione spiegata
Prima creiamo i gruppi con GROUP BY, poi filtriamo i gruppi con HAVING.
SELECT cliente_id, COUNT(*) AS numero_ordiniFROM ordiniGROUP BY cliente_idHAVING COUNT(*) >= 2;HAVING lavora sul risultato aggregato, non sulle singole righe iniziali.
Esercizio 28
Sezione intitolata “Esercizio 28”Dalla tabella prodotti (categoria, prezzo), mostrare le categorie con prezzo medio superiore a 50.
Soluzione spiegata
Anche qui il filtro riguarda una media di gruppo, quindi serve HAVING.
SELECT categoria, AVG(prezzo) AS prezzo_medioFROM prodottiGROUP BY categoriaHAVING AVG(prezzo) > 50;Il database calcola la media per categoria e poi tiene solo i gruppi sopra 50.
Esercizio 29
Sezione intitolata “Esercizio 29”Dalle tabelle clienti (id, nome) e ordini (id, cliente_id, totale), mostrare nome del cliente e totale dell’ordine usando una INNER JOIN.
Soluzione spiegata
INNER JOIN collega solo le righe che trovano una corrispondenza in entrambe le tabelle.
SELECT clienti.nome, ordini.totaleFROM clientiINNER JOIN ordini ON clienti.id = ordini.cliente_id;La condizione dopo ON spiega come abbinare clienti e ordini.
Esercizio 30
Sezione intitolata “Esercizio 30”Dalle tabelle clienti (id, nome) e ordini (cliente_id, totale), mostrare tutti i clienti anche se non hanno ordini.
Soluzione spiegata
Per tenere tutte le righe della tabella di sinistra usiamo LEFT JOIN.
SELECT clienti.nome, ordini.totaleFROM clientiLEFT JOIN ordini ON clienti.id = ordini.cliente_id;Se un cliente non ha ordini, nelle colonne di ordini comparira NULL.
Esercizio 31
Sezione intitolata “Esercizio 31”Dalle tabelle clienti (id, nome, citta) e ordini (cliente_id, totale), mostrare nome e totale degli ordini dei clienti di Roma.
Soluzione spiegata
Combiniamo una JOIN con un filtro WHERE.
SELECT clienti.nome, ordini.totaleFROM clientiINNER JOIN ordini ON clienti.id = ordini.cliente_idWHERE clienti.citta = 'Roma';Prima colleghiamo le tabelle, poi teniamo solo le righe dei clienti di Roma.
Esercizio 32
Sezione intitolata “Esercizio 32”Dalle tabelle clienti (id, nome) e ordini (cliente_id, totale), mostrare i nomi dei clienti con alias di tabella c e i totali con alias di tabella o.
Soluzione spiegata
Gli alias corti rendono la query piu compatta nelle join.
SELECT c.nome, o.totaleFROM clienti AS cINNER JOIN ordini AS o ON c.id = o.cliente_id;c e o sono solo soprannomi temporanei usati dentro questa query.
Esercizio 33
Sezione intitolata “Esercizio 33”Dalla tabella ordini (id, totale), mostrare i 3 ordini con totale piu alto.
Soluzione spiegata
Prima ordiniamo in modo decrescente, poi limitiamo il risultato.
SELECT id, totaleFROM ordiniORDER BY totale DESCLIMIT 3;Senza ORDER BY, le tre righe mostrate non sarebbero necessariamente quelle con totale piu alto.
Esercizio 34
Sezione intitolata “Esercizio 34”Dalla tabella prodotti (nome, prezzo), mostrare i prodotti con prezzo compreso tra 10 e 50, ordinati dal prezzo piu basso al piu alto.
Soluzione spiegata
Usiamo due condizioni numeriche e poi ordiniamo il risultato.
SELECT nome, prezzoFROM prodottiWHERE prezzo >= 10 AND prezzo <= 50ORDER BY prezzo ASC;La query tiene solo i prodotti nel range richiesto e li dispone in ordine crescente.
Esercizio 35
Sezione intitolata “Esercizio 35”Dalla tabella clienti (nome, citta, attivo), contare quanti clienti attivi ci sono per ogni citta.
Soluzione spiegata
Prima filtriamo i clienti attivi, poi raggruppiamo per citta.
SELECT citta, COUNT(*) AS clienti_attiviFROM clientiWHERE attivo = TRUEGROUP BY citta;WHERE agisce prima del raggruppamento e lascia solo le righe utili al conteggio.
Esercizio 36
Sezione intitolata “Esercizio 36”Dalla tabella ordini (cliente_id, totale), mostrare i clienti con una spesa totale superiore a 200, ordinando dal totale piu alto al piu basso.
Soluzione spiegata
Serve una somma per cliente, un filtro sul gruppo e un ordinamento finale.
SELECT cliente_id, SUM(totale) AS totale_spesoFROM ordiniGROUP BY cliente_idHAVING SUM(totale) > 200ORDER BY totale_speso DESC;La query produce prima i totali per cliente, poi tiene solo quelli sopra 200 e li ordina.
Esercizio 37
Sezione intitolata “Esercizio 37”Dalla tabella prodotti (nome, prezzo), mostrare i prodotti con prezzo superiore alla media dei prezzi.
Soluzione spiegata
La media viene calcolata in una subquery e confrontata nella query esterna.
SELECT nome, prezzoFROM prodottiWHERE prezzo > ( SELECT AVG(prezzo) FROM prodotti);La query interna produce un solo valore, che la query esterna usa come soglia.
Esercizio 38
Sezione intitolata “Esercizio 38”Dalla tabella clienti (id, nome) e dalla tabella ordini (cliente_id), mostrare i clienti che hanno fatto almeno un ordine.
Soluzione spiegata
Possiamo usare una subquery con IN per confrontare l’id del cliente con la lista dei cliente_id.
SELECT nomeFROM clientiWHERE id IN ( SELECT cliente_id FROM ordini);La subquery costruisce la lista degli id presenti negli ordini, poi la query esterna trova i nomi corrispondenti.
Esercizio 39
Sezione intitolata “Esercizio 39”Dalla tabella clienti (id, nome) e dalla tabella ordini (cliente_id, totale), mostrare i clienti che hanno almeno un ordine con totale maggiore di 100.
Soluzione spiegata
La subquery restringe prima gli ordini, poi la query esterna recupera i clienti giusti.
SELECT nomeFROM clientiWHERE id IN ( SELECT cliente_id FROM ordini WHERE totale > 100);La soluzione segue un ragionamento in due passaggi molto naturale.
Esercizio 40
Sezione intitolata “Esercizio 40”Creare una CTE con nome ordini_grandi che contenga gli ordini con totale > 100, poi mostrare id, cliente_id e totale.
Soluzione spiegata
Con WITH diamo un nome chiaro al risultato intermedio.
WITH ordini_grandi AS ( SELECT id, cliente_id, totale FROM ordini WHERE totale > 100)SELECT id, cliente_id, totaleFROM ordini_grandi;La CTE rende il passaggio intermedio esplicito e piu leggibile di una query annidata.
Esercizio 41
Sezione intitolata “Esercizio 41”Creare una CTE ordini_grandi con gli ordini sopra 100, poi mostrare il nome del cliente e il totale dell’ordine.
Soluzione spiegata
La CTE prepara i dati; la query principale li collega ai clienti.
WITH ordini_grandi AS ( SELECT id, cliente_id, totale FROM ordini WHERE totale > 100)SELECT clienti.nome, ordini_grandi.totaleFROM ordini_grandiINNER JOIN clienti ON clienti.id = ordini_grandi.cliente_id;Separare i due passaggi aiuta a leggere la query come una piccola sequenza logica.
Esercizio 42
Sezione intitolata “Esercizio 42”Dalla tabella ordini (id, data_ordine, totale), mostrare gli ordini dal piu recente al piu vecchio.
Soluzione spiegata
Per avere prima le date piu nuove ordiniamo in modo decrescente.
SELECT id, data_ordine, totaleFROM ordiniORDER BY data_ordine DESC;Questo ordinamento e molto comune quando si consultano cronologie o liste di attivita.
Esercizio 43
Sezione intitolata “Esercizio 43”Dalla tabella ordini (id, data_ordine, totale), mostrare i 10 ordini piu recenti.
Soluzione spiegata
Uniamo ordinamento per data e limitazione delle righe.
SELECT id, data_ordine, totaleFROM ordiniORDER BY data_ordine DESCLIMIT 10;Prima decidiamo quali righe vengono per prime, poi ne prendiamo solo dieci.
Esercizio 44
Sezione intitolata “Esercizio 44”Dalla tabella clienti (id, nome) e dalla tabella ordini (cliente_id), mostrare i clienti che non hanno ordini.
Soluzione spiegata
Con LEFT JOIN teniamo tutti i clienti e poi cerchiamo quelli senza corrispondenza.
SELECT clienti.nomeFROM clientiLEFT JOIN ordini ON clienti.id = ordini.cliente_idWHERE ordini.cliente_id IS NULL;Se la join non trova ordini, le colonne della tabella ordini diventano NULL.
Esercizio 45
Sezione intitolata “Esercizio 45”Dalla tabella clienti (id, nome, email), contare quante email risultano presenti.
Soluzione spiegata
COUNT(email) conta solo le righe in cui email non e NULL.
SELECT COUNT(email) AS email_presentiFROM clienti;Questo esercizio mostra la differenza tra contare le righe e contare i valori effettivamente presenti in una colonna.
Esercizio 46
Sezione intitolata “Esercizio 46”Dalla tabella clienti (citta, attivo), mostrare le citta con almeno 3 clienti attivi.
Soluzione spiegata
Filtriamo prima i clienti attivi e poi usiamo HAVING sul conteggio per citta.
SELECT citta, COUNT(*) AS numero_clienti_attiviFROM clientiWHERE attivo = TRUEGROUP BY cittaHAVING COUNT(*) >= 3;La query combina il filtro sulle righe con il filtro finale sui gruppi.
Esercizio 47
Sezione intitolata “Esercizio 47”Dalla tabella prodotti (categoria, prezzo), mostrare per ogni categoria il numero di prodotti e il prezzo medio.
Soluzione spiegata
Possiamo calcolare piu valori aggregati nello stesso raggruppamento.
SELECT categoria, COUNT(*) AS numero_prodotti, AVG(prezzo) AS prezzo_medioFROM prodottiGROUP BY categoria;Ogni riga del risultato riassume una categoria con due informazioni diverse.
Esercizio 48
Sezione intitolata “Esercizio 48”Dalle tabelle clienti (id, nome) e ordini (cliente_id, totale), mostrare il totale speso da ogni cliente con il relativo nome.
Soluzione spiegata
Qui una JOIN porta il nome del cliente, mentre SUM() calcola la spesa complessiva.
SELECT clienti.id, clienti.nome, SUM(ordini.totale) AS totale_spesoFROM clientiINNER JOIN ordini ON clienti.id = ordini.cliente_idGROUP BY clienti.id, clienti.nome;La query unisce i dati delle due tabelle e poi riassume gli ordini per cliente.
Esercizio 49
Sezione intitolata “Esercizio 49”Dalle tabelle clienti (id, nome, attivo) e ordini (cliente_id, totale), mostrare il totale speso solo dai clienti attivi.
Soluzione spiegata
Filtriamo i clienti attivi e poi raggruppiamo i loro ordini.
SELECT clienti.id, clienti.nome, SUM(ordini.totale) AS totale_spesoFROM clientiINNER JOIN ordini ON clienti.id = ordini.cliente_idWHERE clienti.attivo = TRUEGROUP BY clienti.id, clienti.nome;Il filtro WHERE entra in gioco prima della somma finale.
Esercizio 50
Sezione intitolata “Esercizio 50”Creare una CTE totali_clienti che calcoli la spesa totale per ogni cliente, poi mostrare solo i clienti con totale superiore a 200.
Soluzione spiegata
La CTE separa il calcolo dei totali dal filtro finale, rendendo la query piu leggibile.
WITH totali_clienti AS ( SELECT cliente_id, SUM(totale) AS totale_speso FROM ordini GROUP BY cliente_id)SELECT cliente_id, totale_spesoFROM totali_clientiWHERE totale_speso > 200;Prima costruiamo il riepilogo per cliente, poi lavoriamo su quel risultato come se fosse una tabella temporanea.