Aller au contenu
Lecture (DQL)

Ordre logique d'exécution

Une requête ne s'évalue pas dans l'ordre où on l'écrit : FROM vient d'abord, SELECT presque à la fin. Connaître cet ordre explique la plupart des erreurs d'alias et d'agrégats.

  • ordre
  • exécution
  • évaluation
  • alias
  • FROM WHERE GROUP BY HAVING

Syntaxe

Modèle
-- Ordre d'écriture        Ordre logique d'évaluationSELECT ...               -- 5. SELECT (puis 6. DISTINCT)FROM ... JOIN ...        -- 1. FROM et jointuresWHERE ...                -- 2. WHEREGROUP BY ...             -- 3. GROUP BYHAVING ...               -- 4. HAVINGORDER BY ...             -- 7. ORDER BYLIMIT ...                -- 8. LIMIT / OFFSET

Exemple

Exemple concret
SELECT city, COUNT(*) AS nb_clients     -- 5. on calcule les colonnesFROM customers                          -- 1. on part de la tableWHERE email LIKE '%@email.com'          -- 2. on filtre les lignesGROUP BY city                           -- 3. on forme un groupe par villeHAVING COUNT(*) >= 2                    -- 4. on filtre les groupesORDER BY nb_clients DESC, city          -- 7. l'alias existe déjà iciLIMIT 10;-- Jeu de données : boutique-- Résultat attendu (Marseille, avec un seul client, est écartée par HAVING) :-- Lyon | 2-- Paris | 2

À retenir

  1. Conséquence directe : un alias créé dans SELECT est connu dans ORDER BY, mais pas dans WHERE, GROUP BY ni HAVING en SQL standard. SQLite et MySQL le tolèrent, PostgreSQL et SQL Server le refusent.
  2. Piège : WHERE COUNT(*) > 1 est une erreur, car WHERE est évalué avant le regroupement. Un filtre sur un agrégat va dans HAVING.
  3. Piège : les fonctions de fenêtre (ROW_NUMBER, RANK…) sont calculées avec SELECT, donc après WHERE. Pour filtrer sur leur résultat, enveloppez la requête dans une CTE ou une sous-requête.
  4. C'est un ordre logique, pas physique : l'optimiseur peut lire un index avant la table ou appliquer un filtre plus tôt, du moment que le résultat est identique.

Voir aussi