W3docs

Comprendre la clause MySQL ORDER BY en PHP

La clause ORDER BY trie les résultats d'une requête MySQL. Apprenez la syntaxe, l'ordre ascendant/descendant, les valeurs NULL et la sécurité en PHP.

Une requête SELECT sans ORDER BY retourne les lignes dans un ordre que MySQL ne garantit pas — il peut changer entre deux exécutions, selon la version du serveur ou après une maintenance de la table. La clause ORDER BY rend cet ordre explicite en triant le jeu de résultats selon une ou plusieurs colonnes. Cette page montre comment l'utiliser depuis PHP : la syntaxe, l'ordre ascendant ou descendant, le tri par plusieurs colonnes, l'emplacement des valeurs NULL, et comment trier par une colonne fournie par l'utilisateur en toute sécurité pour éviter une faille d'injection SQL.

Si vous débutez avec l'exécution de requêtes depuis PHP, commencez par la connexion à MySQL et la sélection de données.

Syntaxe

SELECT column1, column2, ...
FROM table_name
ORDER BY column1 [ASC | DESC], column2 [ASC | DESC], ...;
  • ASC trie par ordre croissant (A→Z, 0→9, du plus ancien au plus récent) et est la valeur par défautORDER BY age et ORDER BY age ASC sont identiques.
  • DESC trie par ordre décroissant (Z→A, 9→0, du plus récent au plus ancien).
  • La direction s'applique par colonne, vous pouvez donc les mélanger : ORDER BY country ASC, age DESC.

ORDER BY s'exécute après le filtrage WHERE et le GROUP BY, il ne trie donc que les lignes qui ont survécu à ces étapes. C'est la dernière clause avant LIMIT.

Un exemple de base

Ceci sélectionne les noms et les âges et trie les clients les plus âgés en premier :

<?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();
?>

On se connecte avec la classe mysqli, on sélectionne name et age dans customers, et on utilise ORDER BY age DESC pour que l'âge le plus élevé apparaisse en premier. Remplacez DESC par ASC (ou supprimez-le) pour afficher les plus jeunes en premier.

Tri par plusieurs colonnes

Lorsque plusieurs lignes partagent la même valeur dans la première colonne de tri, la colonne suivante départage les égalités. L'ordre des colonnes dans la clause est l'ordre de priorité :

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

Ceci regroupe les clients par country par ordre alphabétique, et au sein de chaque pays liste les plus âgés en premier. Avec les données ci-dessous :

namecountryage
AnnaCanada41
BenCanada29
CarlaMexico50

ORDER BY country ASC, age DESC retourne Anna, Ben, Carla — Canada avant Mexico, et Anna avant Ben car 41 > 29.

Comment les valeurs NULL sont triées

Dans MySQL, NULL est traité comme inférieur à toute valeur non NULL :

  • Avec ASC, les lignes où la colonne de tri est NULL apparaissent en premier.
  • Avec DESC, elles apparaissent en dernier.

Pour forcer les NULL à la fin quelle que soit la direction, triez d'abord sur le fait que la colonne est nulle :

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

last_login IS NULL vaut 0 pour les vraies dates et 1 pour les nulls, donc les lignes non nulles (0) apparaissent avant les nulles (1).

Tri par une colonne choisie à l'exécution (en toute sécurité)

Un besoin courant est de laisser l'utilisateur choisir la colonne de tri — par exemple ?sort=name. Vous ne pouvez pas lier un nom de colonne ou le mot-clé ASC/DESC avec un paramètre de requête préparée ; les paramètres ne fonctionnent que pour les valeurs. Concaténer la requête brute dans le SQL serait une vulnérabilité d'injection SQL. Validez plutôt l'entrée contre une liste blanche :

<?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'utilisateur ne fournit qu'une clé de tableau ; le nom de colonne réel et la direction proviennent de constantes dans votre code, de sorte que les données non fiables n'atteignent jamais la chaîne de requête. C'est le seul endroit où construire du SQL par concaténation est acceptable — parce que chaque valeur possible est une valeur que vous avez écrite.

Remarque : ORDER BY lui-même ne prend jamais de valeurs utilisateur, donc il n'utilise pas de paramètres liés. Toutes les valeurs WHERE dans la même requête doivent toujours être liées avec une requête préparée.

Pièges courants

  • Tri par une colonne de type string contenant des nombres (par exemple un age stocké en VARCHAR) trie de manière lexicale : "10" vient avant "9". Stockez les nombres dans une colonne numérique, ou convertissez avec ORDER BY CAST(age AS UNSIGNED).
  • ORDER BY avec LIMIT est la façon d'obtenir les "N meilleurs" résultats : ORDER BY age DESC LIMIT 5 retourne les cinq plus âgés. Sans ORDER BY, les lignes que LIMIT conserve sont imprévisibles. Voir limiter les données.
  • Trier un grand jeu de résultats peut être lent si aucun index ne couvre la colonne de tri ; un index sur la colonne ORDER BY permet à MySQL de sauter l'étape de tri.

Conclusion

ORDER BY transforme un ordre de lignes indéfini en un ordre défini. Retenez l'essentiel : ASC est la valeur par défaut, les colonnes sont appliquées de gauche à droite pour les départages, NULL trie bas, et une colonne de tri choisie par l'utilisateur doit être validée contre une liste blanche plutôt que concaténée aveuglément. Combiné avec WHERE pour le filtrage et LIMIT pour la pagination, cela vous donne un contrôle total sur les lignes retournées et leur ordre.

Pratique

Pratique
Quel est le but de la clause ORDER BY dans MySQL tel que décrit sur le site ?
Quel est le but de la clause ORDER BY dans MySQL tel que décrit sur le site ?
Was this page helpful?