samedi 1 janvier 2022

[SQL] SQL Query Order of Execution

Introduction :

L’ordre d’exécution des requêtes SQL est un concept essentiel pour comprendre comment écrire des requêtes sans erreur qui s’exécutent efficacement.

Problème :

Lors de l’écriture de requêtes SQL, nous écrivons généralement les clauses dans cet ordre : SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, puis LIMIT. Cependant, l’ordre dans lequel la base de données interprète la requête est légèrement différent. Cette différence peut entraîner des erreurs ou une inefficacité lors de l’exécution des requêtes.

Voici quelques exemples de mauvaises pratiques liées à l’ordre des opérations SQL qui peuvent ne pas donner le résultat attendu :

  1. Utilisation de HAVING avant GROUP BY : La clause HAVING est utilisée pour filtrer les résultats après l’agrégation des données avec GROUP BY. Si vous utilisez HAVING avant GROUP BY, vous obtiendrez une erreur car HAVING ne peut pas fonctionner sur des données non agrégées. Par exemple :

    SELECT COUNT(*), department
    FROM employees
    HAVING COUNT(*) > 5
    GROUP BY department;
    

    Cette requête générera une erreur car HAVING est utilisé avant GROUP BY.

  2. Utilisation de alias de colonne dans WHERE : Les alias de colonne définis dans SELECT ne sont pas accessibles dans WHERE, car WHERE est exécuté avant SELECT. Par exemple :

    SELECT salary * 0.9 AS adjusted_salary
    FROM employees
    WHERE adjusted_salary > 50000;
    

    Cette requête générera une erreur car adjusted_salary n’est pas accessible dans WHERE.

  3. Utilisation de LIMIT dans une sous-requête : En SQL standard, LIMIT n’est pas autorisé dans les sous-requêtes. Par exemple :

    SELECT employee_id, salary
    FROM (
        SELECT employee_id, salary
        FROM employees
        ORDER BY salary DESC
        LIMIT 10
    ) AS top_employees;
    

    Cette requête peut générer une erreur dans certains systèmes de gestion de bases de données qui suivent strictement le standard SQL.

Ces exemples illustrent l’importance de comprendre l’ordre d’exécution des opérations SQL pour éviter les erreurs et obtenir les résultats attendus.

Solution :  

Pour résoudre ce problème, il est important de comprendre l’ordre d’exécution réel des requêtes SQL:

  1. FROM : La première partie de la requête que la base de données lira est la clause FROM. Ce sont les tables dont nous extrayons les données.
  2. WHERE : La clause WHERE est l’endroit où nous filtrons les lignes de la table.
  3. GROUP BY : La clause GROUP BY est souvent utilisée en conjonction avec des fonctions d’agrégation pour renvoyer une agrégation de résultats regroupés par une ou plusieurs colonnes.
  4. HAVING : La clause HAVING nous permet de filtrer un ensemble de résultats après que les données ont été regroupées et agrégées.
  5. SELECT : L’instruction SELECT est l’endroit où nous définissons les colonnes et les fonctions d’agrégation que nous voulons renvoyer en tant que colonnes sur notre table.
  6. DISTINCT : DISTINCT vient plus tard dans l’ordre des opérations, car il supprime les lignes en double après que toutes les lignes ont été sélectionnées.
  7. UNION : Une union prend deux requêtes qui peuvent toutes deux se tenir seules en tant que requêtes valides et les empile l’une sur l’autre pour se combiner en une seule.

corrections :

  1. Mauvaise pratique : Utilisation de HAVING avant GROUP BY

    SELECT COUNT(*), department
    FROM employees
    HAVING COUNT(*) > 5
    GROUP BY department;
    

    Correction : Utilisez HAVING après GROUP BY.

    SELECT COUNT(*), department
    FROM employees
    GROUP BY department
    HAVING COUNT(*) > 5;
    
  2. Mauvaise pratique : Utilisation de alias de colonne dans WHERE

    SELECT salary * 0.9 AS adjusted_salary
    FROM employees
    WHERE adjusted_salary > 50000;
    

    Correction : Utilisez l’alias de colonne dans HAVING ou déplacez le calcul dans WHERE.

    SELECT salary * 0.9 AS adjusted_salary
    FROM employees
    HAVING adjusted_salary > 50000;
    
    -- ou
    
    SELECT salary * 0.9 AS adjusted_salary
    FROM employees
    WHERE salary * 0.9 > 50000;
    
  3. Mauvaise pratique : Utilisation de LIMIT dans une sous-requête

    SELECT employee_id, salary
    FROM (
        SELECT employee_id, salary
        FROM employees
        ORDER BY salary DESC
        LIMIT 10
    ) AS top_employees;
    

    Correction : Utilisez LIMIT dans la requête principale.

    SELECT employee_id, salary
    FROM employees
    ORDER BY salary DESC
    LIMIT 10;
    

Discussion 

Comprendre cet ordre d’exécution peut vous aider à diagnostiquer pourquoi une requête ne s’exécute pas et vous aidera à optimiser vos requêtes pour qu’elles s’exécutent plus rapidement

Par exemple, parce que la clause FROM vient avant la clause WHERE, vous pouvez filtrer les résultats avec une CTE avant de les joindre dans votre requête finale pour optimiser votre requête.

https://www.sisense.com/blog/sql-query-order-of-operations/