CodeGym /Cours /SQL SELF /Erreurs typiques lors de l'utilisation des fonctions wind...

Erreurs typiques lors de l'utilisation des fonctions window

SQL SELF
Niveau 30 , Leçon 4
Disponible

Bon, il est temps de parler des galères qui peuvent arriver quand tu utilises les fonctions window. Comme souvent en dev (et dans la vie), c'est mieux d'apprendre sur les fails des autres. On va décortiquer les erreurs classiques que font les débutants (et même parfois les devs expérimentés), et voir comment les éviter.

Erreur n°1 : Mauvaise utilisation de PARTITION BY

Un des fails les plus fréquents, c’est d’oublier ou de mal configurer le paramètre PARTITION BY, surtout si tu veux splitter tes données en groupes. Sans ça, PostgreSQL va voir toutes les lignes comme un seul gros groupe, et du coup, les résultats risquent d’être bien chelous par rapport à ce que tu voulais.

Imaginons qu’on a une table sales qui contient des infos sur les ventes :

id région mois total
1 Nord 2023-01 1000
2 Sud 2023-01 800
3 Nord 2023-02 1200
4 Sud 2023-02 900

Tu veux calculer la somme cumulée (SUM()) des ventes par mois pour chaque région. Tu pourrais écrire une requête comme ça :

SELECT
    region,
    month,
    SUM(total) OVER (ORDER BY month) AS running_total
FROM 
    sales;

Résultat :

région mois running_total
Nord 2023-01 1000
Sud 2023-01 1800
Nord 2023-02 3000
Sud 2023-02 3900

À première vue, ça a l’air OK. Mais en vrai, le résultat ne colle pas à ce qu’on attend, parce que la somme cumulée est faite sur toutes les lignes, pas par région. Le souci, c’est qu’on a zappé PARTITION BY region.

Code corrigé :

SELECT 
    region,
    month,
    SUM(total) OVER (PARTITION BY region ORDER BY month) AS running_total
FROM 
    sales;

Résultat :

région mois running_total
Nord 2023-01 1000
Nord 2023-02 2200
Sud 2023-01 800
Sud 2023-02 1700

Maintenant, c’est bon : les données sont groupées par région, et la somme cumulée est calculée séparément pour chaque région.

Erreur n°2 : Mauvais ordre dans ORDER BY

ORDER BY à l’intérieur de OVER() gère l’ordre des lignes dans la fenêtre. Si tu te plantes dans l’ordre, les résultats risquent d’être bizarres.

Tu veux calculer les sommes cumulées des ventes, triées par mois décroissant. Tu pourrais écrire une requête comme ça :

SELECT
    month,
    total,
    SUM(total) OVER (ORDER BY month DESC) AS running_total
FROM 
    sales;

Résultat :

mois total running_total
2023-02 1200 1200
2023-02 900 2100
2023-01 1000 3100
2023-01 800 3900

À première vue, ça a l’air correct, mais fais gaffe : les lignes sont groupées par mois, mais la somme n’est pas calculée correctement à cause de l’ordre décroissant. C’est pour ça que les résultats sont chelous.

Correction : réécris la requête en utilisant le bon ordre dans ORDER BY :

SELECT
    month,
    total,
    SUM(total) OVER (ORDER BY month ASC) AS running_total
FROM 
    sales;

Erreur n°3 : Utiliser les fonctions window sans index

Les fonctions window bossent souvent sur des gros volumes de données, et si t’as pas d’index sur les colonnes clés, tu risques de flinguer les perfs.

Exemple : on a une table large_sales avec des millions de lignes, et on veut calculer le rang des ventes :

SELECT
    id,
    total,
    RANK() OVER (ORDER BY total DESC) AS rank
FROM 
    large_sales;

Sur un petit jeu de données, ça passe vite, mais sur des millions de lignes, ça peut prendre une éternité.

Correction : ajoute un index sur la colonne utilisée dans ORDER BY :

CREATE INDEX idx_total ON large_sales(total DESC);

Maintenant, la requête va tourner beaucoup plus vite.

Erreur n°4 : Mal comprendre la fenêtre définie par ROWS ou RANGE

Quand tu utilises ROWS et RANGE, c’est super important de piger comment ils calculent la fenêtre de lignes. Si tu piges pas bien ces mots-clés, tu risques d’avoir des résultats inattendus.

Exemple : tu veux calculer la moyenne mobile des ventes pour le mois courant et les deux précédents :

SELECT
    month,
    AVG(total) OVER (ORDER BY month ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM 
    sales;

Si à la place de ROWS tu mets RANGE :

SELECT
    month,
    AVG(total) OVER (ORDER BY month RANGE BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM 
    sales;

Le résultat sera différent, parce que RANGE bosse sur des plages de valeurs, pas sur un nombre précis de lignes.

Erreur n°5 : Utiliser trop de fonctions window

Si tu utilises plusieurs fonctions window dans une même requête, tu risques de faire des calculs en double et de ralentir grave tes perfs.

Exemple :

SELECT 
    id,
    total,
    SUM(total) OVER (PARTITION BY region) AS region_total,
    SUM(total) OVER (PARTITION BY region) / COUNT(total) OVER (PARTITION BY region) AS region_avg
FROM 
    sales;

Ici, SUM(total) et COUNT(total) sont recalculés plusieurs fois pour chaque ligne.

Correction : raccourcis la requête avec des sous-requêtes ou un CTE :

WITH cte_region_totals AS (
    SELECT 
        region,
        SUM(total) AS region_total,
        COUNT(total) AS region_count
    FROM 
        sales
    GROUP BY 
        region
)
SELECT 
    s.id,
    s.total,
    t.region_total,
    t.region_total / t.region_count AS region_avg
FROM 
    sales s
JOIN 
    cte_region_totals t ON s.region = t.region;

Tips pour éviter les erreurs

Vérifie PARTITION BY et ORDER BY : checke toujours si ta fenêtre est bien définie.

Indexe tes données : surtout si tu fais des tris (ORDER BY) ou des filtres.

Utilise les CTE pour les calculs multiples : ça t’aide à éviter les doublons dans les calculs.

Mate le plan d’exécution : utilise EXPLAIN et EXPLAIN ANALYZE pour voir comment PostgreSQL gère ta requête.

Teste sur des vraies données : assure-toi que les résultats collent à ce que tu veux et que tes besoins sont bien couverts.

1
Étude/Quiz
Configuration du frame de fenêtre, niveau 30, leçon 4
Indisponible
Configuration du frame de fenêtre
Configuration du frame de fenêtre
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION