W3docs

Comprendere la clausola MySQL ORDER BY in PHP

La clausola ORDER BY ordina i risultati di una query MySQL per una o più colonne. Scopri come usarla in PHP in modo sicuro.

Una query SELECT senza ORDER BY restituisce le righe in un ordine che MySQL non garantisce — può cambiare tra esecuzioni, versioni del server o dopo operazioni di manutenzione della tabella. La clausola ORDER BY rende quell'ordine esplicito, ordinando il risultato per una o più colonne. Questa pagina mostra come usarla da PHP: la sintassi, l'ordinamento crescente e decrescente, l'ordinamento per più colonne, dove si posizionano i valori NULL e come ordinare per una colonna specificata dall'utente in sicurezza, evitando vulnerabilità di SQL injection.

Se sei alle prime armi con l'esecuzione di query da PHP, inizia prima con la connessione a MySQL e la selezione dei dati.

Sintassi

SELECT column1, column2, ...
FROM table_name
ORDER BY column1 [ASC | DESC], column2 [ASC | DESC], ...;
  • ASC ordina in modo crescente (A→Z, 0→9, dal più vecchio al più recente) ed è il valore predefinitoORDER BY age e ORDER BY age ASC sono identici.
  • DESC ordina in modo decrescente (Z→A, 9→0, dal più recente al più vecchio).
  • La direzione si applica per colonna, quindi puoi mischiarle: ORDER BY country ASC, age DESC.

ORDER BY viene eseguito dopo il filtraggio WHERE e il GROUP BY, quindi ordina solo le righe che hanno superato quei passaggi. È l'ultima clausola prima di LIMIT.

Un esempio di base

Questo seleziona nomi ed età e ordina i clienti più anziani prima:

<?php

$conn = new mysqli("localhost", "username", "password", "database");
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

$sql = "SELECT name, age FROM customers ORDER BY age DESC";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
    while ($row = $result->fetch_assoc()) {
        echo "Name: " . $row["name"] . " - Age: " . $row["age"] . "<br>";
    }
} else {
    echo "0 results";
}

$conn->close();
?>

Ci connettiamo con la classe mysqli, selezioniamo name e age da customers, e usiamo ORDER BY age DESC in modo che l'età più alta venga prima. Sostituisci DESC con ASC (o rimuovilo) per mettere prima i più giovani.

Ordinamento per più colonne

Quando più righe condividono lo stesso valore nella prima colonna di ordinamento, la colonna successiva risolve il pareggio. L'ordine delle colonne nella clausola è l'ordine di precedenza:

SELECT name, country, age
FROM customers
ORDER BY country ASC, age DESC;

Questo raggruppa i clienti per country in ordine alfabetico, e all'interno di ogni paese elenca prima i più anziani. Con i dati seguenti:

nomepaeseetà
AnnaCanada41
BenCanada29
CarlaMexico50

ORDER BY country ASC, age DESC restituisce Anna, Ben, Carla — Canada prima di Mexico, e Anna prima di Ben perché 41 > 29.

Come si ordinano i valori NULL

In MySQL, NULL viene trattato come inferiore a qualsiasi valore non-NULL:

  • Con ASC, le righe in cui la colonna di ordinamento è NULL compaiono prima.
  • Con DESC, compaiono ultime.

Per forzare i NULL alla fine indipendentemente dalla direzione, ordina prima in base al fatto che la colonna sia null:

SELECT name, last_login
FROM users
ORDER BY last_login IS NULL, last_login DESC;

last_login IS NULL restituisce 0 per le date reali e 1 per i null, quindi le righe non-null (0) vengono prima di quelle null (1).

Ordinamento per una colonna scelta a runtime (in sicurezza)

Un'esigenza comune è permettere all'utente di scegliere la colonna di ordinamento — ad esempio ?sort=name. Non è possibile legare un nome di colonna o la parola chiave ASC/DESC con un segnaposto di prepared statement; i segnaposto funzionano solo per i valori. Concatenare la richiesta grezza nell'SQL sarebbe una vulnerabilità di SQL injection. Valida invece l'input rispetto a un elenco consentito:

<?php
// Map user input to known-good column names.
$allowedColumns = [
    "name" => "name",
    "age"  => "age",
    "date" => "created_at",
];

$sortKey   = $_GET["sort"] ?? "name";
$column    = $allowedColumns[$sortKey] ?? "name";          // fallback if unknown
$direction = (($_GET["dir"] ?? "asc") === "desc") ? "DESC" : "ASC";

// $column and $direction can now only be values we put in the code.
$sql = "SELECT name, age FROM customers ORDER BY $column $direction";
$result = $conn->query($sql);
?>

L'utente fornisce solo una chiave dell'array; il nome effettivo della colonna e la direzione provengono da costanti nel tuo codice, quindi l'input non attendibile non raggiunge mai la stringa della query. Questo è l'unico caso in cui costruire SQL tramite concatenazione è accettabile — perché ogni valore possibile è uno che hai scritto tu.

Nota: ORDER BY non utilizza mai valori dell'utente, quindi non usa parametri legati. Eventuali valori WHERE nella stessa query devono comunque essere legati con una prepared statement.

Errori comuni

  • Ordinamento per una colonna stringa con numeri (ad es. un age memorizzato come VARCHAR) ordina lessicograficamente: "10" viene prima di "9". Memorizza i numeri in una colonna numerica, o esegui il cast con ORDER BY CAST(age AS UNSIGNED).
  • ORDER BY con LIMIT è il modo per ottenere i "top N" risultati: ORDER BY age DESC LIMIT 5 restituisce i cinque più anziani. Senza ORDER BY, le righe che LIMIT mantiene sono imprevedibili. Consulta limitare i dati.
  • L'ordinamento di un grande risultato può essere lento se nessun indice copre la colonna di ordinamento; un indice sulla colonna ORDER BY permette a MySQL di saltare il passaggio di ordinamento.

Conclusione

ORDER BY trasforma un ordine di righe indefinito in uno definito. Ricorda gli elementi essenziali: ASC è il valore predefinito, le colonne vengono applicate da sinistra a destra per la risoluzione dei pareggi, NULL si ordina in basso, e una colonna di ordinamento scelta dall'utente deve essere validata rispetto a un elenco consentito anziché concatenata ciecamente. Combinato con WHERE per il filtraggio e LIMIT per la paginazione, ti dà il pieno controllo su quali righe restituire e in quale ordine.

Esercitazione

Pratica
Qual è lo scopo dell'istruzione ORDER BY in MySQL come descritto nel sito?
Qual è lo scopo dell'istruzione ORDER BY in MySQL come descritto nel sito?
Was this page helpful?