Quando lavoriamo con i database, non è sufficiente recuperare i dati: spesso abbiamo bisogno di organizzarli in un ordine specifico o di limitare il numero di risultati. MySQL offre alcune istruzioni per farlo, attraverso le clausole ORDER BY, LIMIT e funzioni come COUNT().
In questa lezione vedremo come utilizzare queste funzionalità con Node.js per creare query più efficienti e ottenere esattamente i dati che servono.
La clausola ORDER BY permette di ordinare i risultati di una query in base a una o più colonne. Per impostazione predefinita, l'ordinamento è crescente (dal valore più basso al più alto, oppure in ordine alfabetico dalla A alla Z).
const sql = "SELECT * FROM utenti ORDER BY nome";
con.query(sql, function (err, result) {
if (err) throw err;
console.log(result);
});In questo esempio, i risultati vengono ordinati alfabeticamente in base alla colonna nome. Se avessimo utenti chiamati "Anna", "Mario" e "Luigi", verrebbero restituiti nell'ordine: Anna, Luigi, Mario.
Possiamo specificare esplicitamente l'ordine usando ASC (crescente, valore predefinito) o DESC (decrescente):
// Ordine crescente (A-Z)
const sql1 = "SELECT * FROM utenti ORDER BY nome ASC";
// Ordine decrescente (Z-A)
const sql2 = "SELECT * FROM utenti ORDER BY nome DESC";
// Ordine decrescente per data di registrazione
const sql3 = "SELECT * FROM utenti ORDER BY data_registrazione DESC";L'ordinamento DESC è particolarmente utile quando vogliamo vedere i dati più recenti per primi, come gli ultimi utenti registrati o gli ordini più recenti.
Possiamo ordinare i risultati in base a più colonne contemporaneamente. MySQL ordina prima per la prima colonna. Se due righe hanno lo stesso valore, usa la seconda colonna come criterio successivo, e così via:
const sql = "SELECT * FROM prodotti ORDER BY categoria ASC, prezzo DESC";
con.query(sql, function (err, result) {
if (err) throw err;
console.log(result);
});In questo esempio, i prodotti vengono prima ordinati per categoria (alfabeticamente), e all'interno di ogni categoria vengono ordinati per prezzo dal più alto al più basso.
I valori NULL vengono trattati in modo speciale nell'ordinamento. Con ASC, i valori NULL appaiono per primi, mentre con DESC appaiono per ultimi:
// NULL appare per primo
const sql1 = "SELECT * FROM utenti ORDER BY telefono ASC";
// NULL appare per ultimo
const sql2 = "SELECT * FROM utenti ORDER BY telefono DESC";La clausola LIMIT permette di limitare il numero di risultati restituiti da una query. È essenziale per migliorare le prestazioni quando lavoriamo con tabelle che contengono molti dati.
const sql = "SELECT * FROM utenti LIMIT 10";
con.query(sql, function (err, result) {
if (err) throw err;
console.log(result);
});Questo esempio restituisce solo i primi 10 utenti della tabella.
Per implementare la paginazione (come quella che vedi sui siti web quando ci sono più pagine di risultati), possiamo combinare LIMIT con OFFSET:
const paginaCorrente = 2;
const elementiPerPagina = 10;
const offset = (paginaCorrente - 1) * elementiPerPagina;
const sql = "SELECT * FROM prodotti LIMIT ? OFFSET ?";
con.query(sql, [elementiPerPagina, offset], function (err, result) {
if (err) throw err;
console.log(result);
});Nell'esempio:
LIMIT 10 indica che vogliamo 10 risultati per pagina.OFFSET 10 indica di saltare i primi 10 risultati e partire dall'undicesimo.OFFSET 0 (primi 10 risultati).OFFSET 10 (risultati dall'11 al 20).OFFSET 20 (risultati dal 21 al 30).MySQL offre anche una sintassi abbreviata per LIMIT con OFFSET:
const sql2 = "SELECT * FROM utenti LIMIT 20, 10";Nella sintassi abbreviata LIMIT offset, count, il primo numero è l'offset e il secondo è il numero di risultati da restituire.
Spesso combiniamo ORDER BY e LIMIT per ottenere i primi risultati secondo un criterio. Ad esempio, per trovare i 5 prodotti più costosi:
const sql = "SELECT * FROM prodotti ORDER BY prezzo DESC LIMIT 5";
con.query(sql, function (err, result) {
if (err) throw err;
console.log("I 5 prodotti più costosi:");
result.forEach(prodotto => {
console.log(`${prodotto.nome}: €${prodotto.prezzo}`);
});
});La funzione COUNT() è progettata per contare le righe che soddisfano specifici criteri di una query, ottenendo il totale senza la necessità di recuperare i dati effettivi.
const sql = "SELECT COUNT(*) AS totale FROM utenti";
con.query(sql, function (err, result) {
if (err) throw err;
console.log("Numero totale di utenti:", result[0].totale);
});Nell'esempio:
COUNT(*) conta tutte le righe della tabella.AS totale dà un nome al risultato, così possiamo restituirlo facilmente con result[0].totale.Possiamo combinare COUNT() con WHERE per contare solo le righe che soddisfano determinati criteri:
const sql = "SELECT COUNT(*) AS attivi FROM utenti WHERE stato = 'attivo'";
con.query(sql, function (err, result) {
if (err) throw err;
console.log("Utenti attivi:", result[0].attivi);
});L'istruzione SQL dell'esempio restituisce il numero di utenti attivi nel database.
COUNT(*) conta tutte le righe, incluse quelle con valori NULL. Se vogliamo contare solo le righe dove una specifica colonna non è NULL, usiamo COUNT(nome colonna):
const sql = "SELECT COUNT(telefono) AS con_telefono FROM utenti";
con.query(sql, function (err, result) {
if (err) throw err;
console.log("Utenti con telefono:", result[0].con_telefono);
});Per contare solo i valori unici in una colonna, possiamo usare COUNT(DISTINCT nome colonna):
const sql = "SELECT COUNT(DISTINCT citta) AS citta_diverse FROM utenti";
con.query(sql, function (err, result) {
if (err) throw err;
console.log("Numero di città diverse:", result[0].citta_diverse);
});Questo è utile, ad esempio, per sapere da quante città diverse provengono gli utenti.
Possiamo creare query complesse combinando queste istruzioni. Ad esempio, per trovare le 3 categorie di prodotti più popolari:
const sql = `SELECT categoria, COUNT(*) AS numero_prodotti
FROM prodotti
GROUP BY categoria
ORDER BY numero_prodotti DESC
LIMIT 3`;
con.query(sql, function (err, result) {
if (err) throw err;
console.log("Le 3 categorie più popolari:");
result.forEach(riga => {
console.log(`${riga.categoria}: ${riga.numero_prodotti} prodotti`);
});
});In questo esempio:
GROUP BY categoria raggruppa i prodotti per categoria.COUNT(*) conta quanti prodotti ci sono in ogni categoria.ORDER BY numero_prodotti DESC ordina dal gruppo più numeroso.LIMIT 3 restituisce solo le prime 3 categorie.