Fonctions analytiques SQL Oracle – Guide complet

Découvrez les fonctions analytiques Oracle : syntaxe, exemples pratiques et erreurs courantes. Maîtrisez OVER, PARTITION BY et ORDER BY facilement.

Illustration du tutoriel SQL Oracle : Fonctions analytiques SQL Oracle – Guide complet

Publicité

🧪 Envie de pratiquer ? Exécutez les exemples de cet article dans notre SQL Playground gratuit — aucun logiciel à installer.

Fonctions analytiques SQL Oracle : guide complet et exemples pratiques

Les fonctions analytiques Oracle sont parmi les outils les plus puissants du langage SQL pour analyser des données sans réduire le nombre de lignes retournées. Contrairement aux fonctions d’agrégation classiques, les fonctions analytiques Oracle permettent de calculer des totaux cumulés, des rangs, des moyennes mobiles ou des comparaisons entre lignes, tout en conservant le détail de chaque enregistrement. Elles sont incontournables dans les contextes de reporting, de Business Intelligence et d’analyse de données métier.

Définition et utilisation des fonctions analytiques Oracle

Une fonction analytique (ou window function) calcule une valeur pour chaque ligne d’un résultat en se basant sur un ensemble de lignes voisines appelé fenêtre (window). Ce comportement la distingue fondamentalement des fonctions d’agrégation comme SUM() ou AVG() utilisées avec GROUP BY, qui réduisent plusieurs lignes en une seule.

En entreprise, les fonctions analytiques Oracle sont utilisées pour :

  • Classer des éléments : classement des meilleurs vendeurs par région, des produits les plus vendus par catégorie.
  • Calculer des totaux cumulés : suivi du chiffre d’affaires cumulé mois par mois.
  • Comparer une ligne à ses voisines : afficher la valeur du mois précédent ou suivant (LAG, LEAD).
  • Calculer des parts de marché : ratio d’une valeur individuelle sur un total de groupe.
  • Identifier des doublons ou des écarts : détecter les lignes dupliquées avec ROW_NUMBER().

Parmi les fonctions analytiques les plus utilisées sous Oracle, on trouve : ROW_NUMBER(), RANK(), DENSE_RANK(), SUM(), AVG(), COUNT(), MIN(), MAX(), LAG(), LEAD(), FIRST_VALUE(), LAST_VALUE() et NTILE().

Syntaxe des fonctions analytiques Oracle

La syntaxe générale d’une fonction analytique Oracle est la suivante :

fonction_analytique() OVER (
    [PARTITION BY colonne1, colonne2, ...]
    [ORDER BY colonne3 [ASC|DESC]]
    [ROWS | RANGE BETWEEN ... AND ...]
)

Voici le détail de chaque clause :

  • fonction_analytique() : la fonction à appliquer (SUM, RANK, LAG, etc.).
  • OVER() : clause obligatoire qui indique à Oracle qu’il s’agit d’une fonction analytique. Sans elle, la fonction est traitée comme une agrégation classique.
  • PARTITION BY : divise le résultat en groupes indépendants (similaire à GROUP BY mais sans réduire les lignes). Optionnel : si absent, toute la table forme une seule partition.
  • ORDER BY : définit l’ordre des lignes au sein de chaque partition pour le calcul. Obligatoire pour les fonctions de classement (RANK, ROW_NUMBER) et les fonctions de décalage (LAG, LEAD).
  • ROWS | RANGE BETWEEN ... AND ... : définit précisément la fenêtre de calcul autour de la ligne courante. Par exemple, ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW pour un cumul depuis le début.

Exemples pratiques de fonctions analytiques Oracle

Exemple 1 – Classement des vendeurs par chiffre d’affaires dans chaque région

Contexte métier : La direction commerciale souhaite identifier le top 3 des vendeurs par région, en se basant sur leur chiffre d’affaires annuel.

-- Classement des vendeurs par CA décroissant, par région
-- RANK() attribue le même rang en cas d'égalité (avec saut de rang suivant)
-- DENSE_RANK() attribue le même rang sans saut

SELECT
    vendeur_id,
    nom_vendeur,
    region,
    chiffre_affaires,
    RANK() OVER (
        PARTITION BY region          -- Une partition par région
        ORDER BY chiffre_affaires DESC  -- Du plus grand CA au plus petit
    ) AS rang_region,
    DENSE_RANK() OVER (
        PARTITION BY region
        ORDER BY chiffre_affaires DESC
    ) AS rang_dense_region
FROM vendeurs
ORDER BY region, rang_region;

Résultat attendu : Chaque vendeur conserve sa ligne avec son CA. La colonne rang_region indique sa position dans sa région. Si deux vendeurs ont le même CA, RANK() attribuera le rang 1 aux deux, puis passera au rang 3, tandis que DENSE_RANK() passera au rang 2.

Exemple 2 – Calcul du total cumulé du CA mensuel et comparaison avec le mois précédent

Contexte métier : Le service financier souhaite suivre l’évolution mensuelle des ventes avec un cumul progressif sur l’année et l’affichage du CA du mois précédent pour mesurer la progression.

-- Cumul progressif du CA et comparaison avec le mois précédent
-- LAG() permet d'accéder à la valeur d'une ligne précédente
-- SUM() OVER avec fenêtre cumulative calcule le total progressif

SELECT
    annee,
    mois,
    ca_mensuel,
    -- Total cumulé depuis le début de l'année
    SUM(ca_mensuel) OVER (
        PARTITION BY annee              -- Repart à zéro chaque année
        ORDER BY mois
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS ca_cumule,
    -- CA du mois précédent (NULL pour le 1er mois)
    LAG(ca_mensuel, 1, 0) OVER (
        PARTITION BY annee
        ORDER BY mois
    ) AS ca_mois_precedent,
    -- Écart en valeur absolue vs mois précédent
    ca_mensuel - LAG(ca_mensuel, 1, 0) OVER (
        PARTITION BY annee
        ORDER BY mois
    ) AS ecart_vs_precedent
FROM ventes_mensuelles
ORDER BY annee, mois;

Résultat attendu : Chaque ligne de résultat affiche le CA du mois, son cumul depuis janvier, le CA du mois précédent et l’écart. Le paramètre 0 dans LAG(ca_mensuel, 1, 0) est la valeur par défaut retournée pour le premier mois (pas de mois précédent).

Publicité

Erreurs courantes avec les fonctions analytiques Oracle

Erreur : utiliser une fonction analytique dans la clause WHERE

Problème : Il est tentant de filtrer directement sur le résultat d’une fonction analytique dans la clause WHERE. Oracle renvoie alors une erreur ORA-00904 ou un comportement inattendu.

-- ❌ INCORRECT : Oracle n'autorise pas les fonctions analytiques dans WHERE
SELECT vendeur_id, nom_vendeur, chiffre_affaires,
       RANK() OVER (ORDER BY chiffre_affaires DESC) AS rang
FROM vendeurs
WHERE RANK() OVER (ORDER BY chiffre_affaires DESC) <= 3; -- ERREUR !

Solution : Il faut encapsuler la requête dans une sous-requête ou utiliser une CTE (Common Table Expression) avec WITH, puis filtrer dans la requête externe.

-- ✅ CORRECT : filtrage via une sous-requête
SELECT *
FROM (
    SELECT vendeur_id, nom_vendeur, chiffre_affaires,
           RANK() OVER (ORDER BY chiffre_affaires DESC) AS rang
    FROM vendeurs
)
WHERE rang <= 3;

Résumé des fonctions analytiques Oracle

Point cléDétail
Clause obligatoireOVER() — indique qu’il s’agit d’une fonction analytique
PartitionnementPARTITION BY — divise les données en groupes indépendants
Ordre de calculORDER BY dans OVER() — définit le tri au sein de la fenêtre
Fenêtre de calculROWS / RANGE BETWEEN — précise les bornes de la fenêtre
Fonctions de classementRANK(), DENSE_RANK(), ROW_NUMBER(), NTILE()
Fonctions de décalageLAG(), LEAD(), FIRST_VALUE(), LAST_VALUE()
Fonctions d’agrégation analytiquesSUM(), AVG(), COUNT(), MIN(), MAX()
Filtrage sur résultatToujours via une sous-requête ou une CTE, jamais dans WHERE

Bonnes pratiques Oracle

  1. Préférez les CTEs (WITH) pour améliorer la lisibilité : lorsque vous combinez plusieurs fonctions analytiques ou que vous devez filtrer sur leurs résultats, l’utilisation d’une CTE rend le code plus lisible et plus facile à maintenir qu’une imbrication de sous-requêtes.
  2. Soyez précis sur la clause de fenêtrage (ROWS vs RANGE) : par défaut, Oracle utilise RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW dès qu’un ORDER BY est présent dans OVER(). Ce comportement peut inclure des lignes ayant la même valeur que la ligne courante. Utilisez explicitement ROWS BETWEEN pour un contrôle précis des lignes incluses dans la fenêtre.

Aller plus loin

Pour approfondir votre maîtrise des fonctions analytiques et du SQL Oracle, nous vous recommandons ces lectures complémentaires :

Sur le même thème

Un nouveau tutoriel SQL par semaine

Nous ne spammons pas ! Consultez notre politique de confidentialité pour plus d’informations.

Publicité

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Publicité