09. Les fonctions

A présent les exemples seront illustrés avec des données provenant d'une entreprise d'e-commerce vendant des articles de sports. Il y a de nombreuses tables mais nous allons nous concentrer pour le moment sur :

  • La table factInternetSale qui concerne les articles commandés.
  • La table dimProduct qui donne les caractéristiques des différents produits.

Un aperçu de la table factInternetSale dans la base de données adventureWork.

ProductKey OrderDateKey DueDateKey ShipDateKey CustomerKey SalesTerritoryKey SalesOrderNumber OrderQuantity UnitPrice UnitPriceDiscountPct ProductStandardCost TaxAmt Freight OrderDate DueDate ShipDate
346 20110701 20110713 20110708 11750 7 SO43698 6 3399.99 0.15 1912.1544 271.9992 84.9998 2011-07-01 00:00:00.000 2011-07-13 00:00:00.000 2011-07-08 00:00:00.000
346 20110701 20110713 20110708 15827 1 SO43699 4 3399.99 0 1912.1544 271.9992 84.9998 2011-07-01 00:00:00.000 2011-07-13 00:00:00.000 2011-07-08 00:00:00.000
311 20110702 20110714 20110709 13163 4 SO43702 9 3578.27 0 2171.2942 286.2616 89.9998 2011-07-04 00:00:00.000 2011-07-10 00:00:00.000 2011-07-08 00:00:00.000
ProductKey : Clé du produit.
OrderDateKey : Clé de la date de commande.
DueDateKey : Clé de la date d'échéance.
ShipDateKey : Clé de la date d'expédition.
CustomerKey : Clé du client.
SalesTerritoryKey : Clé du territoire de vente.
SalesOrderNumber : Numéro de commande de vente.
OrderQuantity : Quantité commandée.
UnitPrice : Prix unitaire hors taxe (HT).
UnitPriceDiscountPct : Pourcentage de réduction sur le prix unitaire.
ProductStandardCost : Coût standard du produit (unitaire).
TaxAmt : Montant de la taxe.
Freight : Frais d'expédition.
Attention : Chaque ligne de cette table représente la vente d'un type d'article par commande.


Un aperçu de la table dimProduct dans la base de données adventureWork.
ProductKey ProductAlternateKey ProductSubcategoryKey WeightUnitMeasureCode SizeUnitMeasureCode EnglishProductName SpanishProductName StandardCost FinishedGoodsFlag SafetyStockLevel ReorderPoint StartDate EndDate Status
1 AR-5381 NULL NULL NULL Adjustable Race NULL NULL 0 1000 750 1998-06-01 00:00:00.000 NULL Current
2 BA-8327 NULL NULL NULL Bearing Ball NULL NULL 0 1000 750 1998-06-01 00:00:00.000 NULL Current
3 BE-2349 NULL NULL NULL BB Ball Bearing NULL NULL 0 800 600 1998-06-01 00:00:00.000 NULL Current
ProductKey : Clé du produit.
ProductAlternateKey : Clé alternative du produit.
ProductSubcategoryKey : Clé de la sous-catégorie du produit.
WeightUnitMeasureCode : Code de l'unité de mesure du poids.
SizeUnitMeasureCode : Code de l'unité de mesure de la taille.
EnglishProductName : Nom du produit en anglais.
StandardCost : Coût standard.
FinishedGoodsFlag : Indicateur de produit fini.
SafetyStockLevel : Niveau de stock de sécurité.
ReorderPoint : Point de réapprovisionnement.
StartDate : Date de début.
EndDate : Date de fin.
Status : Statut du produit.

Les fonctions

Les fonctions sont conçues pour traiter des données en entrée (input) et produire des données transformées en sortie (output).

La plupart des fonctions se terminent par des parenthèses, comme SUM(), DATE() ou MEDIAN(). À l'intérieur des parenthèses, on place ce qu'on appelle des arguments. Ce sont les informations ou valeurs que la fonction utilise pour effectuer son calcul ou sa transformation. Par exemple :

  • Dans SUM(1, 2, 3), les arguments 1, 2, et 3 sont les valeurs que la fonction additionne.
  • Dans DATE(2024, 11, 15), les arguments correspondent à l'année, le mois et le jour pour construire une date.

Les arguments sont séparés par des virgules ',' ce qui permet de passer plusieurs éléments à une même fonction.

Type de données en entrée

Les fonctions s'appliquent aux colonnes (ou champs) d'une table, chacune étant associée à un type de données spécifique comme VARCHAR, INT, ou DATE. Pour fonctionner correctement, une fonction attend que les données du champ respectent ce type. Ci-dessous, des exemples de type de données:

Nom Alias Description Exemples
BIT BITSTRING Chaîne de 1 et 0 '101010'
BOOLEAN BOOL, LOGICAL Booléen logique (vrai/faux) TRUE
BLOB BYTEA, BINARY, VARBINARY Données binaires de longueur variable 0×54686973206973206120424C4F4221
DATE Date du calendrier (année, mois, jour) '2023-12-14'
DOUBLE FLOAT8, NUMERIC, DECIMAL Nombre à virgule flottante double précision (8 octets) 3.141592653589793
INTEGER INT4, INT, SIGNED Entier signé sur quatre octets 2147483647
INTERVAL Delta date/heure INTERVAL '1' DAY
REAL FLOAT4, FLOAT Nombre à virgule flottante simple précision (4 octets) 2.71828
TIME Heure du jour (sans fuseau horaire) '15:30:00'
TIMESTAMP DATETIME Combinaison de l'heure et de la date '2023-12-14 15:30:00'
TIMESTAMP WITH TIME ZONE TIMESTAMPTZ Combinaison de l'heure et de la date avec fuseau horaire '2023-12-14 15:30:00+00:00'
VARCHAR CHAR, BPCHAR, TEXT, STRING, OBJET Chaîne de caractères de longueur variable 'Hello, World!'

Bien que les fonctions soient beaucoup utilisées dans la clause SELECT, elles peuvent également être utilisées dans d'autres clauses telles que WHERE , GROUP BY ou HAVING (qui n'ont pas encore été vues). Ici on distinguera 3 types de fonctions, chacune ayant un rôle spécifique dans le traitement des données :

  • Celles qui agissent sur les lignes,
  • Celles qui agissent sur les agrégats,
  • Celles qui agissent sur les fenêtres.
/* 
La colonne orderDate doit être une date afin que YEAR( ) 
puisse extraire l'année de la commande. 
*/
SELECT DISTINCT YEAR(orderDate)
FROM factInternetSale ;

Fonctions de Lignes

Les fonctions de ligne, aussi appelé "row level function" sont les plus simples et les plus communément utilisées. Elles renvoient une valeur transformée par ligne.


Chaque valeur est associée à une valeur transformée par la fonction. Le nombre de lignes avant et après la transformation est le même.
/* 
Affiche les colonnes mentionnées ainsi que la colonne qui compte 
le nombre de jours entre la prise de commande et l'envoie du colis. 
*/
SELECT orderDate, shipDate, DAY(shipDate - orderDate) AS preparationDay
FROM factInternetSale
LIMIT 3 ;
DAY( ), renvoie pour chaque ligne le nombre de jours pour préparer une commande.

Question 9.1

Dans la table factInternetSale dans la base de données adventureWork, afficher les lignes où la préparation de commande (le temps entre l'enregistrement de la commande et l'envoie) prend moins d'une semaine. Pour accéder à la console SQL.
Rappel : Les fonctions peuvent aussi être utilisé dans le WHERE.


ROUND( )

Nous avons utilisé des fonctions de lignes sur des données de type date mais on peut également le faire pour d'autres type de fonction. À présent, nous allons utiliser la fonction ROUND( ) qui agit sur des données décimales. ROUND( ) prend 2 arguments, la colonne choisie et le nombre de décimales utilisées pour arrondir le résultat.

/* */
SELECT salesOrderNumber, ROUND(ProductStandardCost,0) as ProductStandardCost, 
       ROUND(UnitPrice,0) as UnitPrice
FROM factInternetSale
LIMIT 3 ;
ROUND( ) renvoie les colonnes correspondant au coûts du produit (**ProductStandardCost**) et le montant de vente (**UnitPrice**) arrondi à l'entier près (car le second argument est 0).

Question 9.2

Dans la table factInternetSale , afficher la marge brute réalisée pour chaque type de produits de chaque commande enregistrée au mois de juillet 2011. Le résultat doit être affiché avec uniquement 2 chiffres après la virgule. Pour accéder à la console SQL.

  • Rappel 1 : Une ligne correspond à un type de produit dans une commande.
  • Rappel 2 : La marge brute est la différence (HT) entre le prix de vente et le coût de revient.


Question 9.3

Dans la table dimProduct, afficher tous les produits qui ont dans leur nom "ball" que ce soit en minuscule ou majuscule. Pour accéder à la console SQL.
Rappel : Selon la version de SQL utilisée, l'opérateur LIKE peut être sensible aux majuscules et minuscules. Afin d'être sûr de trouver un résultat, une bonne pratique est d'ajouter la fonction LOWER( ) qui transforme tous les caractères en minuscule, ensuite l'opérateur LIKE cherche les caractères correspondant en minuscule.



CONCAT( )

La fonction CONCAT( ) est utilisée pour combiner plusieurs chaînes de caractères, qu'elles proviennent de valeurs fixes ou de colonnes d'une table. Elle peut être appliquée à chaque ligne d'une table pour concaténer les valeurs de plusieurs colonnes en une seule chaîne. Par exemple, si vous avez une colonne pour les prénoms et une autre pour les noms, vous pouvez les combiner pour former un nom complet.

Fonction Description Exemple Résultat
CONCAT(column1, ' ', column2) Concatène les valeurs de plusieurs colonnes ou chaînes CONCAT(first_name, ' ', last_name) John Doe
CONCAT('Order #', order_id) Ajoute un préfixe ou suffixe à une valeur de colonne CONCAT('Order #', 12345) Order #12345

Question 9.4

La fonction CONCAT( ) permet de concaténer 2 chaines de caractères. Utilise cette fonction pour créer la colonne Newname dans la table dimProduct qui aura le format suivant :

ProductKey ProductAlternateKey EnglishProductName NewName
1 AR-5381 Adjustable Race AR-5381: Adjustable Race
2 BA-8327 Bearing Ball BA-8327: Bearing Ball
3 BE-2349 BB Ball Bearing BE-2349: BB Ball Bearing

Pour accéder à la console SQL.



CASE WHEN

Les fonctions appliquées aux lignes peuvent être utilisées avec tous types de données. La plupart d'entre elles nécessitent des parenthèses pour recevoir des arguments, bien qu'il existe quelques exceptions.
Parmi ces exceptions, l'expression conditionnelle CASE WHEN se distingue : elle permet d'exécuter différentes opérations selon une ou plusieurs conditions. Cette expression peut être comparée à une structure IF( ) dans des langages comme Excel, Python, R ou JavaScript.

Voici comment fonctionne la syntaxe générale de la fonction CASE WHEN.

CASE
   WHEN condition1 THEN résultat1
   WHEN condition2 THEN résultat2
   ...
   ELSE résultat_par_défaut
END
CASE : Le mot-clé qui commence la déclaration CASE WHEN.
WHEN : Chaque WHEN spécifie une condition à évaluer.
THEN : Indique le résultat à retourner si la condition associée est vraie.
ELSE : Indique le résultat à retourner si aucune des conditions précédentes n'est vraie.
END : Termine la déclaration CASE WHEN.

Évaluation séquentielle : Les conditions sont évaluées de manière séquentielle. La première condition qui est vraie détermine le résultat retourné et les autres conditions ne sont pas évaluées.

CASE
   WHEN x <= 10 THEN 'Un'
   WHEN x <= 20 THEN 'Deux'
   ELSE 'Autre'
END

Si x est inférieur ou égal à 10, le résultat est 'Un' et les conditions suivantes ne sont pas évaluées. Sinon, si x est inférieur ou égal à 20 (et par conséquent de la première condition, supérieur à 10), le résultat est 'Deux' et les conditions suivantes ne seront pas évaluées. Si les 2 cas précédents ne sont pas vérifiés, le résultat est 'Autre'.

x Categorie
5 Un
15 Deux
25 Autre



Conditions multiples : Vous pouvez utiliser des opérateurs logiques tels que AND, OR et NOT pour créer des conditions plus complexes.

CASE
   WHEN (age >= 18 AND gender = 'Femme') OR (age >= 21 AND gender = 'Homme') THEN 'Admissible'
   ELSE 'Non Admissible'
END 

la condition ELSE permet de définir un résultat par défaut si aucune des conditions précédentes n'est vraie. Par conséquent, il est fortement recommandé de toujours mettre une valeur par défaut.

Si une personne est une femme de 18 ans ou plus ou un homme de 21 ans ou plus, le résultat est 'Admissible'. Sinon, le résultat est 'Non Admissible'.

age gender Résultat
20 Femme Admissible
25 Homme Admissible
17 Femme Non Admissible
20 Homme Non Admissible



Dans l'exemple ci-dessous, la nouvelle colonne profit est créee. Elle prend les valeurs "petit", "moyen", "grand" ou "très grand" en fonction de la marge obtenu à la vente pour les produits qui ne sont pas vendus à perte.
SELECT salesOrderNumber, ProductStandardCost, UnitPrice, 
       ROUND(100*(UnitPrice - ProductStandardCost)/ProductStandardCost,2) AS pctProfit,
       CASE WHEN (UnitPrice - ProductStandardCost)/ProductStandardCost < 0.2 THEN 'petit'
            WHEN (UnitPrice - ProductStandardCost)/ProductStandardCost < 0.4 THEN 'moyen'
            WHEN (UnitPrice - ProductStandardCost)/ProductStandardCost < 0.6 THEN 'grand'
            ELSE 'très grand' 
            END AS profit
FROM factInternetSale
WHERE UnitPrice*(1-UnitPriceDiscountPct) > ProductStandardCost ;



Question 9.5

Le total des ventes dans l'exemple ci-dessus est surévalué, il ne tient pas compte des différents rabais attribués (UnitPriceDiscountPct). Recalcule le chiffre d'affaire total en prenant en compte les rabais. On garde 2 chiffres après la virgule. Pour accéder à la console SQL.




Fonction d'agregation

Les fonctions d'agrégation, également appelées "aggregate functions," permettent de calculer une valeur unique à partir d'un ensemble de lignes. Contrairement aux fonctions de ligne, elles résument les données, par exemple en calculant une moyenne AVG( ), une somme SUM( ), un maximum MAX( ) ou encore un décompte COUNT( ).

SUM( )

L'utilisation de la fonction SUM( ) sur les colonnes productStandardCost et orderQuantity, renvoie la somme des coûts de tous les produits vendus. Les décimales sont aussi affichées.

/* Affiche le total des coûts des produits vendus pour l'année 2011 */
SELECT SUM(orderQuantity*productStandardCost) as orderProductCost
FROM factInternetSale
WHERE OrderDateKey LIKE '2011%' ;



Question 9.6

Que fait cette requête? Pour accéder à la console SQL.

SELECT ROUND(SUM(OrderQuantity*ProductStandardCost),0) as orderProductCost
FROM factInternetSale
WHERE YEAR(OrderDate) = 2013 ;



Question 9.7

Comment afficher le chiffre d'affaire total sur le premier semestre 2012. Le chiffre d'affaire total sera renommé salesAmount, il doit être affiché sans chiffre après la virgule. Pour accéder à la console SQL.


MIN( ), MAX( ), AVG( )

Une même colonne peut être utilisée avec différentes statistiques. Si on veut connaitre le coût minimal, maximal et moyen on écrira:

-- Affiche la commande avec le coût minimal, maximal et moyen des produits vendus pour l'année 2011.
SELECT MIN(OrderQuantity*ProductStandardCost) as minOrderProductCost,
       MAX(OrderQuantity*ProductStandardCost) as maxOrderProductCost,
       AVG(OrderQuantity*ProductStandardCost) as avgOrderProductCost
FROM factInternetSale
WHERE OrderDateKey LIKE '2011%' ;

Attention : Lorsque des fonctions d'agrégation sont utilisées, on ne peut pas afficher des colonnes sans fonction d'agrégation sinon une erreur se produit. Pour palier à ce problème, il faut utiliser la clause GROUP BY qui sera vue par la suite.




Question 9.8

Affiche la marge totale réalisée sur l'ensemble des commandes du mois de juillet 2011. Le résultat doit être affiché avec uniquement 2 chiffres après la virgule. Pour accéder à la console SQL.


COUNT( )

La fonction COUNT( ) est souvent utilisé en SQL, elle permet de compter le nombre de lignes pour lesquelles la colonne spécifiée a une valeur non nulle. Illustrons l'utilisation de la fonction COUNT( ) avec la table prospects.

ID Prenom Telephone Mail Ville
1 Bernard 0123456789 bernard@gmail.com Paris
2 Leila (null) lla@gmail.com Lyon
3 Ben 9876543210 (null) Lyon
4 Salah (null) salah@microsoft.com Paris


COUNT( nom_colonne ) ignore donc toutes les lignes où la colonne nom_colonne a une valeur nulle. Par exemple, si le nombre de prospects est compté en se basant sur la colonne telephone :

SELECT COUNT(telephone) 
FROM prospects ;

Le résultat renvoyé sera 2. Seuls les prospects où le numéro de téléphone est renseigné sont comptés.

Pour compter toutes les lignes de la table, qu'elles aient ou non des valeurs nulles dans certaines colonnes, il faut utiliser COUNT( * ). De cette manière est compté le nombre total de lignes dans une table. Par exemple, si vous voulez connaître le nombre total de prospects dans la table prospects, y compris ceux qui ont des données manquantes :

SELECT COUNT(*) 
FROM prospects ;


Question 9.9

Identifier la bonne table à sélectionner pour compter le nombre de produits dans la base de données adventureWork? Pour accéder à la console SQL.



A présent, si tu souhaites savoir combien de valeurs uniques existent dans une colonne, il faut utiliser COUNT( DISTINCT nom_colonne ). Par exemple, si tu souhaites savoir de combien de villes différentes proviennent tes prospects :

SELECT COUNT(DISTINCT VILLE) 
FROM prospects ;

Le résultat renvoyé sera 2. Chaque ville ne sera comptée qu'une seule fois, même si Paris et Marseille apparaissent plusieurs fois dans la table prospects.



Question 9.10

Compter le nombre de clients (uniques) ayant effectué un achat au cours de l'année 2011? Pour accéder à la console SQL.



En résumé

  1. Pour compter le nombre total de lignes d'une table, COUNT( * ) est le bon choix.
  2. Pour compter le nombre de lignes non nulles dans une certaine colonne alors utilise COUNT( nom_colonne ).
  3. Pour connaitre le nombre valeurs uniques dans une colonne alors utilise COUNT( DISTINCT nom_colonne ).
Fonctions Description et Utilisation Exemples
SUM() Calcule la somme totale d'une colonne numérique. SELECT SUM(salaire) FROM employes; (somme des salaires)
AVG() Calcule la moyenne d'une colonne numérique. SELECT AVG(salaire) FROM employes; (moyenne des salaires)
MIN() Trouve la valeur minimale d'une colonne. SELECT MIN(salaire) FROM employes; (salaire le plus bas)
MAX() Trouve la valeur maximale d'une colonne. SELECT MAX(salaire) FROM employes; (salaire le plus élevé)
COUNT(*) Compte le nombre total de lignes dans une table, indépendamment de la présence de valeurs nulles. SELECT COUNT(*) FROM employes; (nombre total d'employés)
COUNT(nom_colonne) Compte le nombre de lignes où la colonne spécifiée a une valeur non nulle. SELECT COUNT(telephone) FROM prospects; (nombre de prospects avec un numéro de téléphone)
COUNT(DISTINCT nom_colonne) Compte le nombre de valeurs distinctes dans une colonne spécifique. SELECT COUNT(DISTINCT ville) FROM prospects; (nombre de villes de provenance des prospects)



Fonction de Fenêtre

Les fonctions de fenêtre, également appelées "Window Functions," permettent d'effectuer des calculs sur un ensemble de lignes tout en conservant le détail de chaque ligne. Par exemple, elles peuvent attribuer un classement RANK( ), calculer des totaux cumulés SUM( ) avec une fenêtre ou des moyennes mobiles AVG( ). Ces fonctions sont particulièrement puissantes pour analyser les données sans les regrouper, contrairement aux fonctions d'agrégation classiques. L'exemple classique est l'ajout d'une colonne attribuant un classement en fonction d'une colonne spécifique.


Imaginons que dans une table fictive nommée personnel, on veuille attribuer un classement des employé par salaires dans chaque service. Les colonnes à disposition sont id, nom, salaire et service.

id nom salaire service
1 Alice 50000 Ventes
2 Bob 48000 Ventes
3 Carol 55000 Ventes
4 David 70000 RH
5 Emma 55000 RH
6 Frank 58000 RH

La fonction de fenêtre va permettre d'ajouter la colonne rangSalaireService. Les lignes ne seront plus classées en fonction de l'identifiant mais en fonction du rang au sein de leur service respectif :


id nom salaire service rangSalaireService
3 Carol 55000 Ventes 1
1 Alice 50000 Ventes 2
2 Bob 48000 Ventes 3
4 David 70000 RH 1
6 Frank 58000 RH 2
5 Emma 55000 RH 3

Voici comment écrire la fonction de fenêtre de notre exemple :

SELECT id, nom, salaire
  ROW_NUMBER( ) OVER (PARTITION BY service ORDER BY salaire DESC) AS rangSalaireService
FROM personnel ;

La fonction ROW_NUMBER( ) attribue un numéro de ligne basé sur l'ordre décroissant des salaires par service. De manière plus générale, la syntaxe d'une fonction de fenêtre est la suivante:

SELECT colonne1, colonne2,
  fonction_fenetre(colonne3) OVER (PARTITION BY colonne_de_partition ORDER BY colonne_ordre)
FROM la_table ;
fonction_fenetre : La fonction de fenêtre appliquée (par exemple, SUM( ), ROW_NUMBER( ), AVG( )).
OVER : Définit le fenêtre sur laquelle la fonction doit être appliquée.
PARTITION BY : Divise l'ensemble des résultats en partitions. Ces partitions sont basées sur les valeurs de colonnes spécifiées.
ORDER BY : Spécifie l'ordre des lignes à l'intérieur de chaque partition.

Attention : Si PARTITION BY et ORDER BY ne sont pas mentionnées, la fonction de fenêtre est par défaut appliquée à l'ensemble du résultat.


/*
Affiche le rang correspondant à l'ordre dans lequel 
l'article commandé est affiché pour chaque client.
*/
SELECT customerKey, orderDate,  
        salesOrderNumber, UnitPrice, 
        ROW_NUMBER() OVER (PARTITION BY customerKey ORDER BY orderDate) AS num_order
FROM factInternetSale
LIMIT 10 ;

Ici la fonction ROW_NUMBER( ) est utilisée. Cependant si 2 lignes ayant la même valeur en critère de tri n'auront pas le même rang. Pour y remédier, il existe la fonction DENSE_RANK( ). Cette fonction attribue le même rang aux lignes partageant des valeurs égales pour le critère de tri. En d'autres termes, les commandes sur plusieurs lignes ou celles effectuées le même jour partageront le même rang.

SELECT customerKey, orderDate,  
        salesOrderNumber, UnitPrice, 
        DENSE_RANK() OVER (PARTITION BY customerKey ORDER BY orderDate) AS num_order
FROM factInternetSale
LIMIT 10 ;

Les lignes ayant la même date de commande auront le même rang.



La fonction SUM( ) peut également être utilisée dans les fonction de fenêtre. Elle permet de calculer des sommes cumulées. Dans l'exemple ci-dessous, la somme est cumulée par client et ordonnée par date et par identifiant produit, de la commande la plus ancienne à la plus récente.
SELECT customerKey, orderDate, ProductKey,  
       salesOrderNumber, UnitPrice, 
       ROUND(UnitPrice*OrderQuantity*(1-UnitPriceDiscountPct),2) as salesAmount,
       SUM(ROUND(UnitPrice*OrderQuantity*(1-UnitPriceDiscountPct),2)) OVER (PARTITION BY customerKey ORDER BY orderDate, ProductKey ) AS cumulOrderAmount
FROM factInternetSale
LIMIT 10 ;

Affiche le montant cumulé de tous les articles achetés pour chaque client au cours du temps.



Les fonctions de fenêtre sont puissantes car elles permettent d'effectuer des calculs basés sur des sous-ensembles spécifiques de lignes, ce qui peut être utile pour l'analyse de données avancée et la génération de rapports.

Question 9.11

Dans la table factInternetSale, ajouter une colonne qui représente le classement de chaque article au sein d'une commande d'un client. Le classement se fera en commençant par l'objet au prix unitaire le plus élevé.
Pour accéder à la console SQL.


Filtrer les Résultats d'une Fonction de Fenêtre

Les fonctions de fenêtre ne peuvent pas être utilisées ailleurs que dans la clause SELECT alors comment filtrer les résultats? Soit il faut utiliser une CTE ou une sous-requête (des notions qui seront vues plus tard), soit en intégrant le mot-clef QUALIFY. Attention : QUALIFY n'est pas utilisable dans tous les SGBD. On peut cependant l'utiliser dans DuckDB, Teradata ou BigQuery.

En utilisant QUALIFY après la clause FROM, il y a la possibilité de spécifier des conditions précises sur les résultats générés par la fonction de fenêtre, offrant ainsi un contrôle plus granulaire sur les données extraites. Cela permet d'affiner les résultats en fonction de critères spécifiques, contribuant ainsi à une analyse plus précise et ciblée des données.

/* Affiche les 2 premières commandes de chaque client. */
SELECT customerKey, orderDate, dueDate,  
        salesOrderNumber, UnitPrice, 
        DENSE_RANK() OVER (PARTITION BY customerKey ORDER BY orderDate) AS num_order
FROM factInternetSale
QUALIFY num_order <= 2 ;
QUALIFY est traité après l'alias créé avec AS dans le SELECT. C'est pourquoi on peut utiliser l'alias dans QUALIFY. Pour simplifier la requête, on peut écrire la fonction de fenêtre uniquement dans QUALIFY sans avoir besoin de la mettre dans le SELECT.
/* Affiche également les 2 premières commandes de chaque client
   mais l'écriture est plus directe. */
SELECT customerKey, orderDate, dueDate,  
        salesOrderNumber, UnitPrice 
FROM factInternetSale
QUALIFY DENSE_RANK() OVER (PARTITION BY customerKey ORDER BY orderDate) <= 2 ;


Ci-dessous, un tableau reprennant les usages des principales fonctions de fenêtre.

Type de Fonction Fonctions Description et Utilisation Exemples
Classement ROW_NUMBER(), RANK(), DENSE_RANK() OVER() Calcule le classement, l'attribution de numéros de ligne sur une fenêtre spécifiée. Utile pour évaluer les meilleures performances. SELECT nom, salaire, ROW_NUMBER() OVER (ORDER BY salaire DESC) FROM employes; (numérotation des employés par salaire décroissant)
Retard LAG() OVER() Renvoie la valeur de la colonne précédente dans une fenêtre spécifiée. Utile pour comparer les valeurs successives. SELECT date, revenu, LAG(revenu) OVER (ORDER BY date) FROM chiffre_affaires; (comparer les revenus d'une date à la date précédente)
Avance LEAD() OVER() Renvoie la valeur de la colonne suivante dans une fenêtre spécifiée. Utile pour anticiper les valeurs successives. SELECT date, revenu, LEAD(revenu) OVER (ORDER BY date) FROM chiffre_affaires; (anticiper les revenus d'une date à la date suivante)
Somme Cumulative SUM() OVER() Calcule la somme cumulée des valeurs dans une colonne pour chaque ligne de la fenêtre spécifiée. Utile pour analyser les tendances d'accumulation. SELECT date, montant, SUM(montant) OVER (ORDER BY date) FROM ventes; (somme cumulative des ventes par date)
Pourcentage par rapport à un Total (Colonne / SUM(Colonne) OVER()) * 100 Calcule le pourcentage d'une colonne par rapport à la somme totale de cette colonne dans la fenêtre spécifiée. Idéal pour évaluer la contribution relative de chaque ligne. SELECT produit, revenu, (revenu / SUM(revenu) OVER ()) * 100 FROM chiffre_affaires; (pourcentage du revenu par produit par rapport au total)
Ajout de conditions QUALIFY condition Permet de filtrer les résultats d'une fonction de fenêtre en appliquant des conditions spécifiques. SELECT produit, quantite, RANK() OVER (ORDER BY quantite DESC) FROM inventaire QUALIFY RANK() <= 10; (les 10 produits les plus vendus)



Question 9.12

Dans la table factInternetSale, afficher les 5 commandes au prix unitaire les plus élevées pour chaque mois de l'année 2014 (ordonner par date).

SQL Console

Category Num Sales Usd
ABC 123 $26.4M
No Results
Retourner vers :

Question 9.1
Question 9.2
Question 9.3
Question 9.4
Question 9.5
Question 9.6
Question 9.7
Question 9.8
Question 9.9
Question 9.10
Question 9.11