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 |
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 |
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 ;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 ;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
ENDWHEN : 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'
ENDSi 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 | 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é
- Pour compter le nombre total de lignes d'une table, COUNT( * ) est le bon choix.
- Pour compter le nombre de lignes non nulles dans une certaine colonne alors utilise COUNT( nom_colonne ).
- 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 ;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 ;/* 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 |
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