SELECT complete con clausole WHERE, ORDER BY e LIMITBETWEEN, IN, LIKE, IS NULL per filtrare le righeDISTINCTLIMIT e OFFSET su dataset realiLa struttura completa della SELECT
La SELECT è il comando più usato in SQL: serve a interrogare il database e ottenere un insieme di righe (detto result set). La sua sintassi segue un ordine ben preciso — e quell’ordine non è casuale: rispecchia l’ordine logico in cui il DBMS elabora le clausole.
SELECT [DISTINCT] colonna1 [AS alias], colonna2, ... FROM tabella [AS alias_tabella] [WHERE condizione] [ORDER BY colonna [ASC | DESC], ...] [LIMIT n [OFFSET m]];
Tra parentesi quadre ci sono le clausole opzionali. La sola obbligatoria è la coppia SELECT … FROM ….
Ordine di esecuzione logico
Il DBMS non legge le clausole nell’ordine in cui le scrivi tu. L’ordine di esecuzione logico è:
| # | Clausola | Cosa fa |
|---|---|---|
| 1 | FROM | Identifica la tabella (o le tabelle) da cui estrarre le righe |
| 2 | WHERE | Filtra le righe applicando le condizioni |
| 3 | SELECT | Seleziona e calcola le colonne del risultato |
| 4 | DISTINCT | Rimuove i duplicati dal result set |
| 5 | ORDER BY | Ordina le righe risultanti |
| 6 | LIMIT / OFFSET | Tronca il result set per la paginazione |
Capire quest’ordine ti evita errori comuni: ad esempio, non puoi usare un alias di colonna definito nella SELECT all’interno della clausola WHERE, perché il DBMS esegue WHERE prima di SELECT e quell’alias non esiste ancora.
La clausola WHERE: filtrare le righe
La clausola WHERE è il cuore delle query di selezione. Contiene una condizione booleana: il DBMS mantiene nel result set solo le righe per cui la condizione è vera.
Operatori di confronto
| Operatore | Significato | Esempio |
|---|---|---|
= | Uguale a | WHERE cognome = 'Rossi' |
<> oppure != | Diverso da | WHERE voto <> 18 |
< > <= >= | Confronto numerico / date | WHERE voto >= 27 |
AND | Entrambe le condizioni vere | WHERE voto >= 18 AND corso_id = 3 |
OR | Almeno una condizione vera | WHERE anno = 1 OR anno = 2 |
NOT | Negazione | WHERE NOT superato = TRUE |
Operatori speciali SQL
BETWEEN … AND … — seleziona valori in un intervallo inclusivo (funziona con numeri, date e stringhe):
-- studenti con voto tra 24 e 30 inclusi SELECT * FROM esame WHERE voto BETWEEN 24 AND 30; -- equivalente esplicito: SELECT * FROM esame WHERE voto >= 24 AND voto <= 30;
IN (…) — verifica se il valore è contenuto in una lista di valori:
-- corsi del primo o del secondo anno SELECT * FROM corso WHERE anno IN (1, 2); -- equivalente OR: SELECT * FROM corso WHERE anno = 1 OR anno = 2;
LIKE — confronto con pattern su stringhe. Due caratteri speciali:
%— qualsiasi sequenza di caratteri (anche vuota)_— esattamente un carattere
-- cognomi che iniziano con "Ros" SELECT * FROM studente WHERE cognome LIKE 'Ros%'; -- nomi di esattamente 4 caratteri SELECT * FROM corso WHERE nome LIKE '____'; -- email di Gmail SELECT * FROM studente WHERE email LIKE '%@gmail.com';
Un pattern che inizia con % (es. '%mario%') non può usare un indice B-tree e provoca una full table scan: su tabelle grandi è molto lento. Usalo con consapevolezza.
IS NULL / IS NOT NULL — in SQL il valore NULL non è uguale a niente, nemmeno a se stesso. Per questo non puoi scrivere WHERE email = NULL: devi usare l’operatore dedicato:
-- studenti senza indirizzo email registrato SELECT nome, cognome FROM studente WHERE email IS NULL; -- studenti con email registrata SELECT nome, cognome FROM studente WHERE email IS NOT NULL;
ORDER BY: ordinare il risultato
ORDER BY ordina il result set secondo uno o più criteri. L’ordine di default è ASC (crescente); va specificato DESC per decrescente.
-- per voto decrescente (dal più alto al più basso) SELECT studente_id, corso_id, voto FROM esame ORDER BY voto DESC; -- prima per anno del corso, poi per nome corso alfabetico SELECT nome, anno FROM corso ORDER BY anno ASC, nome ASC;
I valori NULL vengono messi per ultimi in MySQL (con ASC) e per primi in PostgreSQL. Il comportamento varia tra DBMS.
LIMIT e OFFSET: paginare i risultati
Su tabelle con migliaia di righe, restituire l’intero result set è inefficiente. LIMIT tronca l’output a n righe; OFFSET salta le prime m righe — combinati implementano la paginazione.
-- prima pagina: le prime 10 righe SELECT * FROM studente ORDER BY cognome LIMIT 10; -- seconda pagina: righe 11–20 (salta le prime 10) SELECT * FROM studente ORDER BY cognome LIMIT 10 OFFSET 10; -- terza pagina SELECT * FROM studente ORDER BY cognome LIMIT 10 OFFSET 20;
La formula generale per la pagina p con n righe per pagina è OFFSET = (p - 1) * n.
DISTINCT: eliminare i duplicati
SELECT DISTINCT rimuove le righe duplicate dal result set dopo che le colonne sono state selezionate. È utile quando vuoi ottenere i valori unici di una colonna:
-- lista degli anni in cui sono presenti esami SELECT DISTINCT anno FROM esame_storico ORDER BY anno; -- combinazioni uniche corso–anno SELECT DISTINCT corso_id, anno_accademico FROM iscrizione;
Alias: rinominare colonne e tabelle
La parola chiave AS permette di assegnare un nome temporaneo a una colonna o a una tabella nel context della query. È puramente cosmetico per le colonne, ma diventa necessario per le tabelle quando fai i JOIN (prossima lezione).
-- alias di colonna per rendere l'output più leggibile SELECT nome AS "Nome studente", cognome AS "Cognome", data_nascita AS "Data di nascita" FROM studente; -- alias su espressione calcolata SELECT nome, (crediti * 3) AS ore_totali FROM corso;
Esempi pratici: database scuola
Usiamo il database costruito nelle lezioni precedenti (tabelle STUDENTE, CORSO, ESAME).
Query progressivamente più complesse
-- 1. Tutti gli studenti, ordinati per cognome SELECT nome, cognome FROM studente ORDER BY cognome ASC; -- 2. Studenti nati dopo il 2005 SELECT nome, cognome, data_nascita FROM studente WHERE data_nascita > '2005-12-31' ORDER BY data_nascita; -- 3. Esami superati con lode (voto = 31) SELECT studente_id, corso_id, data_esame FROM esame WHERE voto = 31; -- 4. Corsi del primo anno con meno di 6 crediti SELECT nome, crediti FROM corso WHERE anno = 1 AND crediti < 6 ORDER BY crediti; -- 5. Studenti il cui cognome contiene "ri" SELECT nome, cognome FROM studente WHERE cognome LIKE '%ri%'; -- 6. Esami con voto tra 27 e 30, pagina 1 (10 risultati) SELECT studente_id, corso_id, voto FROM esame WHERE voto BETWEEN 27 AND 30 ORDER BY voto DESC LIMIT 10; -- 7. Lista distinta degli anni in cui esistono corsi SELECT DISTINCT anno AS "Anno di corso" FROM corso ORDER BY anno;
- La
SELECTsegue la sintassi:SELECT … FROM … [WHERE] [ORDER BY] [LIMIT] - L’ordine di esecuzione logico è FROM → WHERE → SELECT → DISTINCT → ORDER BY → LIMIT
BETWEEN,IN,LIKEeIS NULLsono shortcut potenti per condizioni comuni nellaWHERELIKE '%testo%'esegue full scan: lento su tabelle grandi;LIKE 'testo%'può usare un indiceNULLnon si confronta con=: usa sempreIS NULL/IS NOT NULLLIMIT n OFFSET mimplementa la paginazione: formulaOFFSET = (pagina - 1) × n- Gli alias (
AS) rinominano colonne nell’output e diventano obbligatori nei JOIN