Dans cet article
- La clause ORDER BY accepte plusieurs colonnes séparées par des virgules, sans utiliser AND entre elles
- L’ordre de tri s’applique de gauche à droite : la première colonne prime, la seconde départage les égalités
- Chaque colonne peut avoir sa propre direction : ASC ou DESC indépendamment
- ORDER BY se place toujours après WHERE, GROUP BY et HAVING dans l’ordre d’exécution SQL
- Combiner ORDER BY avec GROUP BY et LIMIT permet de créer des classements avancés en quelques lignes
- Les valeurs NULL sont triées en premier ou en dernier selon le SGBD utilisé
Sommaire
- Syntaxe ORDER BY avec plusieurs colonnes
- Pourquoi AND ne fonctionne pas dans ORDER BY
- Exemples pratiques de tri sur plusieurs colonnes
- Mélanger ASC et DESC dans un même ORDER BY
- ORDER BY avec WHERE et GROUP BY : l’ordre compte
- ORDER BY et LIMIT : paginer ses résultats
- Gestion des NULL et pièges courants
- Comparatif du comportement ORDER BY selon les SGBD
- Bonnes pratiques et performances
Quand je corrige des exercices SQL en BTS SIO, je retrouve régulièrement la même erreur : mes étudiants écrivent ORDER BY nom AND prenom en pensant trier sur deux colonnes. C’est logique en français, mais SQL ne fonctionne pas ainsi. La syntaxe correcte utilise une simple virgule pour séparer les colonnes de tri. Dans ce guide, je vous explique comment maîtriser le tri multi-colonnes, éviter les pièges classiques et optimiser vos requêtes.
Syntaxe ORDER BY avec plusieurs colonnes
La clause ORDER BY permet de trier les résultats d’une requête SELECT. Pour trier sur plusieurs colonnes, il suffit de les lister en les séparant par des virgules. Voici la syntaxe générale :
SELECT colonne1, colonne2, colonne3
FROM ma_table
ORDER BY colonne1 ASC, colonne2 DESC, colonne3 ASC;
Le moteur SQL applique le tri de gauche à droite. Concrètement, il trie d’abord tous les enregistrements selon colonne1. Quand plusieurs lignes ont la même valeur pour colonne1, il utilise colonne2 pour les départager. Et si des égalités persistent, colonne3 entre en jeu.
C’est exactement le même principe qu’un annuaire téléphonique : on classe d’abord par nom de famille, puis par prénom pour les homonymes. Il n’y a pas de limite théorique au nombre de colonnes dans un ORDER BY, même si en pratique, dépasser trois ou quatre colonnes de tri est rarement nécessaire.

Par défaut, si vous ne précisez ni ASC ni DESC, SQL applique un tri ascendant (ASC). Les nombres vont du plus petit au plus grand, les chaînes de caractères suivent l’ordre alphabétique, et les dates vont de la plus ancienne à la plus récente.
Pourquoi AND ne fonctionne pas dans ORDER BY
Si vous cherchez « sql order by and » sur un moteur de recherche, c’est probablement parce que vous avez tenté quelque chose comme ceci :
-- ERREUR : cette syntaxe ne fonctionne pas comme attendu
SELECT nom, prenom, ville
FROM etudiants
ORDER BY nom AND prenom;
Cette requête ne génère pas forcément une erreur de syntaxe, et c’est justement le piège. En SQL, AND est un opérateur logique booléen, pas un séparateur de colonnes. L’expression nom AND prenom est interprétée comme une opération booléenne entre deux valeurs. Le résultat est une seule valeur (0 ou 1), et le tri se fait sur cette valeur unique, ce qui produit un résultat incohérent.
La documentation W3Schools sur ORDER BY le confirme : la virgule est le seul séparateur valide entre les colonnes de tri. Voici la correction :
-- CORRECT : virgule entre les colonnes
SELECT nom, prenom, ville
FROM etudiants
ORDER BY nom, prenom;
En résumé, AND appartient à la clause WHERE (pour combiner des conditions), tandis que la virgule appartient à ORDER BY (pour enchaîner les critères de tri). Retenez cette distinction et vous ne ferez plus jamais l’erreur.
Exemples pratiques de tri sur plusieurs colonnes
Prenons une table employes avec les colonnes suivantes : id, nom, prenom, departement, salaire, date_embauche. Voici plusieurs cas concrets que je donne régulièrement en exercice SQL à mes étudiants.
Tri alphabétique par département puis par nom
SELECT nom, prenom, departement
FROM employes
ORDER BY departement ASC, nom ASC, prenom ASC;
Cette requête regroupe visuellement les employés par département (classés de A à Z), puis trie les noms alphabétiquement à l’intérieur de chaque département. Les homonymes sont enfin départagés par prénom.
Classement par salaire décroissant au sein de chaque département
SELECT nom, prenom, departement, salaire
FROM employes
ORDER BY departement ASC, salaire DESC;
Ici, les départements restent en ordre alphabétique, mais à l’intérieur de chaque département, les employés sont classés du salaire le plus élevé au plus bas. C’est typiquement ce qu’on utilise pour générer un rapport par service.
Tri par ancienneté
SELECT nom, prenom, departement, date_embauche
FROM employes
ORDER BY date_embauche ASC, nom ASC;
Les employés les plus anciens apparaissent en premier. Pour ceux embauchés le même jour, le tri alphabétique par nom assure un affichage cohérent et reproductible.

Mélanger ASC et DESC dans un même ORDER BY
Un point que beaucoup de débutants ignorent : chaque colonne de tri peut avoir sa propre direction. Vous n’êtes pas obligé de tout trier dans le même sens. C’est une fonctionnalité puissante que la documentation Microsoft SQL Server détaille pour Transact-SQL, mais le principe est identique sur tous les SGBD.
SELECT nom, prenom, departement, salaire
FROM employes
ORDER BY departement ASC, salaire DESC;
Dans cet exemple, les départements sont triés de A à Z (ASC), mais au sein de chaque département, les salaires sont classés du plus élevé au plus bas (DESC). Ce mélange est parfaitement valide et très courant en production.
Vous pouvez également trier par numéro de position dans la liste SELECT, même si je le déconseille pour la lisibilité :
-- Tri par la 3e colonne ASC, puis la 4e colonne DESC
SELECT nom, prenom, departement, salaire
FROM employes
ORDER BY 3 ASC, 4 DESC;
Cette notation fonctionne, mais si quelqu’un ajoute une colonne dans le SELECT, les numéros se décalent et le tri change silencieusement. Préférez toujours nommer explicitement les colonnes dans ORDER BY.
ORDER BY avec WHERE et GROUP BY : l’ordre compte
L’une des questions les plus fréquentes que je reçois concerne l’ordre des clauses dans une requête SQL. Le moteur SQL exécute les clauses dans un ordre logique précis, différent de l’ordre d’écriture. Voici l’ordre d’exécution :
- FROM : sélection de la table source
- WHERE : filtrage des lignes
- GROUP BY : regroupement
- HAVING : filtrage des groupes
- SELECT : choix des colonnes
- ORDER BY : tri des résultats
- LIMIT : limitation du nombre de lignes
ORDER BY arrive donc en avant-dernière position. C’est logique : on ne peut trier que des résultats déjà filtrés et regroupés. Si vous combinez WHERE avec un LEFT JOIN, le filtrage se fait avant le tri.
Voici un exemple complet qui combine WHERE, GROUP BY et ORDER BY :
SELECT departement, COUNT(*) AS nb_employes, AVG(salaire) AS salaire_moyen
FROM employes
WHERE date_embauche >= '2020-01-01'
GROUP BY departement
HAVING COUNT(*) >= 3
ORDER BY salaire_moyen DESC, departement ASC;
Cette requête filtre d’abord les employés embauchés depuis 2020, les regroupe par département, ne garde que les départements ayant au moins 3 employés, puis trie par salaire moyen décroissant. En cas d’égalité de salaire moyen, le tri alphabétique du département départage. Si vous souhaitez approfondir les agrégations, mon guide sur COUNT DISTINCT en SQL vous sera utile.
ORDER BY et LIMIT : paginer ses résultats
Combiner ORDER BY avec LIMIT (ou TOP sur SQL Server) est la base de toute pagination. Sans ORDER BY, LIMIT retourne des lignes dans un ordre indéterminé, ce qui rend la pagination incohérente entre deux exécutions.
-- Les 10 employés les mieux payés
SELECT nom, prenom, salaire
FROM employes
ORDER BY salaire DESC
LIMIT 10;
-- Page 2 : employés 11 à 20
SELECT nom, prenom, salaire
FROM employes
ORDER BY salaire DESC
LIMIT 10 OFFSET 10;
Pour que la pagination soit déterministe, ajoutez toujours une colonne unique en fin de tri (typiquement la clé primaire). Sinon, deux employés ayant le même salaire pourraient alterner de position entre deux pages :
SELECT nom, prenom, salaire
FROM employes
ORDER BY salaire DESC, id ASC
LIMIT 10 OFFSET 10;
Cette technique est essentielle en développement web. Quand vous construisez une API REST qui retourne une liste paginée, le ORDER BY multi-colonnes garantit la stabilité des résultats entre les appels successifs.

Gestion des NULL et pièges courants
Les valeurs NULL posent un problème récurrent lors du tri. Leur position dans les résultats triés varie selon le SGBD :
- PostgreSQL et Oracle : les NULL apparaissent en dernier en tri ASC (et en premier en DESC)
- MySQL et SQL Server : les NULL apparaissent en premier en tri ASC
PostgreSQL offre la syntaxe NULLS FIRST et NULLS LAST pour contrôler explicitement ce comportement :
-- PostgreSQL : forcer les NULL en fin de liste
SELECT nom, prenom, date_depart
FROM employes
ORDER BY date_depart ASC NULLS LAST;
Sur MySQL, une astuce classique consiste à utiliser ISNULL() ou COALESCE() :
-- MySQL : forcer les NULL en fin de liste
SELECT nom, prenom, date_depart
FROM employes
ORDER BY ISNULL(date_depart), date_depart ASC;
Parmi les autres pièges fréquents que je rencontre en correction de copies d’exercices SQL, voici les plus courants :
- Trier sur une colonne absente du SELECT : c’est autorisé par la norme SQL, mais certains SGBD le refusent quand DISTINCT est utilisé
- Confondre l’alias et le nom de colonne : dans ORDER BY, on peut utiliser l’alias défini dans SELECT (
AS salaire_moyen), mais pas dans WHERE ni HAVING - Oublier ORDER BY avec LIMIT : sans tri explicite, le SGBD retourne les lignes dans un ordre quelconque, souvent l’ordre d’insertion, mais ce n’est jamais garanti
Comparatif du comportement ORDER BY selon les SGBD
Le comportement de ORDER BY est standardisé par la norme SQL ISO/IEC 9075, mais chaque SGBD a ses particularités. Voici un tableau récapitulatif que je distribue à mes étudiants en cours :
| Fonctionnalité | MySQL 8 | PostgreSQL 16 | SQL Server 2022 | Oracle 23c |
|---|---|---|---|---|
| Multi-colonnes (virgule) | Oui | Oui | Oui | Oui |
| Tri par numéro de position | Oui | Oui | Oui | Oui |
| Tri par alias SELECT | Oui | Oui | Oui | Non (sous-requête) |
| NULLS FIRST / LAST | Non (contournement) | Oui | Non (contournement) | Oui |
| NULL en ASC par défaut | En premier | En dernier | En premier | En dernier |
| LIMIT / OFFSET | LIMIT … OFFSET | LIMIT … OFFSET | OFFSET … FETCH NEXT | OFFSET … FETCH NEXT |
| Tri sensible à la casse | Dépend de la collation | Oui (par défaut) | Dépend de la collation | Oui (par défaut) |
Ce tableau montre que la syntaxe de base (virgule entre colonnes, ASC/DESC) est universelle. Les différences portent surtout sur la gestion des NULL et la syntaxe de pagination. Si vous travaillez avec SQL Server 2022, la syntaxe OFFSET FETCH est la méthode recommandée pour la pagination.
Bonnes pratiques et performances
Le tri est une opération coûteuse. Sur une table de plusieurs millions de lignes, un ORDER BY mal optimisé peut transformer une requête instantanée en une attente de plusieurs secondes. Voici mes recommandations concrètes :
Indexez vos colonnes de tri
Un index composite sur les colonnes utilisées dans ORDER BY peut éviter un tri en mémoire (filesort). L’index doit respecter le même ordre de colonnes que le ORDER BY :
-- Index optimisé pour ORDER BY departement ASC, salaire DESC
CREATE INDEX idx_dept_salaire ON employes (departement ASC, salaire DESC);
Sans cet index, le SGBD doit charger toutes les lignes correspondantes, les trier en mémoire, puis retourner le résultat. Avec l’index, les données sont déjà triées sur disque.
Limitez le nombre de colonnes de tri
Chaque colonne supplémentaire dans ORDER BY augmente la complexité du tri. Au-delà de 3 colonnes, demandez-vous si toutes sont réellement nécessaires. Si vous combinez des requêtes avec SQL UNION, le ORDER BY final s’applique au résultat combiné et peut être particulièrement coûteux.
Évitez les expressions calculées dans ORDER BY
-- Lent : le calcul empêche l'utilisation de l'index
SELECT nom, salaire
FROM employes
ORDER BY salaire * 12;
-- Rapide : tri sur la colonne brute, calcul dans SELECT
SELECT nom, salaire, salaire * 12 AS salaire_annuel
FROM employes
ORDER BY salaire;
Une expression dans ORDER BY (multiplication, fonction, concaténation) empêche le moteur d’utiliser un index. Si possible, reformulez pour trier sur la colonne brute. L’utilisation de fonctions comme ROUND en SQL dans un ORDER BY aura le même effet sur les performances.
Utilisez EXPLAIN pour vérifier
Avant de valider une requête en production, vérifiez le plan d’exécution. Sur MySQL, ajoutez EXPLAIN devant votre requête. Sur PostgreSQL, utilisez EXPLAIN ANALYZE. Cherchez les mentions de filesort ou Sort : elles indiquent un tri en mémoire, potentiellement lent sur de gros volumes.
Pour bien documenter vos requêtes SQL avec des commentaires, pensez à expliquer le choix de l’ordre de tri quand il n’est pas évident. Vos collègues vous remercieront.
À retenir
- Séparez les colonnes de tri par une virgule, jamais par AND qui est un opérateur booléen
- Ajoutez ASC ou DESC après chaque colonne pour un tri explicite et lisible
- Placez ORDER BY après WHERE, GROUP BY et HAVING dans votre requête
- Terminez toujours par une colonne unique (clé primaire) pour garantir un tri déterministe avec LIMIT
- Créez un index composite sur vos colonnes ORDER BY fréquentes pour éviter les tris en mémoire
Questions fréquentes
Can we use AND in ORDER BY ?
Non, AND est un opérateur logique booléen réservé à la clause WHERE. Dans ORDER BY, il faut utiliser une virgule pour séparer les colonnes de tri. Écrire ORDER BY colonne1, colonne2 est la seule syntaxe correcte pour trier sur plusieurs critères. Si vous écrivez ORDER BY colonne1 AND colonne2, SQL interprète l’expression comme une opération booléenne et le résultat du tri sera incohérent.
Non, une requête SQL ne peut contenir qu’une seule clause ORDER BY. Pour trier sur deux colonnes, listez-les dans le même ORDER BY en les séparant par une virgule : Peut-on utiliser deux ORDER BY dans une même requête SQL ?
ORDER BY colonne1 ASC, colonne2 DESC. Si vous utilisez des sous-requêtes ou des UNION, seul le ORDER BY de la requête externe (ou finale) est garanti d’être respecté dans le résultat.
WHERE se place toujours avant ORDER BY dans la syntaxe SQL. L’ordre logique est : FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT. Le moteur filtre d’abord les lignes avec WHERE, puis trie le résultat avec ORDER BY. Inverser ces clauses provoque une erreur de syntaxe.Quel est l’ordre entre WHERE et ORDER BY en SQL ?
Oui, c’est très courant. GROUP BY regroupe les lignes et calcule les agrégats (COUNT, SUM, AVG), puis ORDER BY trie le résultat. Par exemple : Peut-on combiner ORDER BY et GROUP BY dans la même requête ?
SELECT departement, COUNT(*) AS total FROM employes GROUP BY departement ORDER BY total DESC. L’ORDER BY peut porter sur une colonne du GROUP BY ou sur un alias d’agrégat défini dans le SELECT.
Utilisez le mot-clé DESC après la colonne concernée : Comment trier par ordre alphabétique inverse en SQL ?
ORDER BY nom DESC. Les chaînes seront classées de Z à A. Vous pouvez combiner avec d’autres colonnes : ORDER BY ville ASC, nom DESC trie les villes de A à Z, puis les noms de Z à A au sein de chaque ville. La sensibilité à la casse dépend de la collation configurée sur votre base de données.
Oui, le tri consomme des ressources, surtout sur les tables volumineuses. Sans index adapté, le SGBD effectue un tri en mémoire (filesort) qui peut être lent. Pour optimiser, créez un index composite sur les colonnes de tri et évitez les expressions calculées dans ORDER BY. Utilisez ORDER BY ralentit-il les requêtes SQL ?
EXPLAIN pour vérifier que votre index est bien utilisé par le moteur.
Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.