Retour à la liste des articles Articles
16 minutes de lecture

Comment utiliser SUM() avec OVER(PARTITION BY) en SQL

Découvrez des cas d'utilisation réels de la fonction SUM() avec la clause OVER(PARTITION BY). Apprenez la syntaxe et consultez 5 exemples différents.

Nous utilisons les fonctions SQL window pour effectuer des opérations sur des groupes de données. Ces opérations comprennent les fonctions mathématiques SUM(), COUNT(), AVG(), et bien d'autres encore. Dans cet article, nous expliquerons ce que fait SUM() avec OVER(PARTITION BY) en SQL. Nous vous montrerons les cas d'utilisation les plus courants dans des applications réelles pour déterminer le rapport entre la valeur d'une ligne individuelle et la valeur totale, calculer les totaux courants et trouver un total de commande personnalisé qui inclut les remises pour certains produits.

Pour obtenir un guide approfondi de l'utilisation de SUM() avec OVER() et d'autres fonctions de fenêtre, suivez notre cours interactif de Fonctions de fenêtrage cours interactif. Il explique en détail tous les concepts des fonctions de fenêtre SQL et comporte plus de 200 exercices.

Commençons.

La clause OVER() en SQL

En SQL, la clause OVER() est utilisée pour introduire les fonctions de fenêtre. La syntaxe générale est la suivante

SELECT …
  <window function> OVER(...)
…

OVER() indique à la base de données que nous voulons utiliser des fonctions de fenêtre. La fonction fenêtre peut être une fonction agrégée, comme SUM(), ou une autre fonction fenêtre.

Une fonction de fenêtre travaille sur un "cadre de fenêtre", ou un ensemble de lignes liées à la ligne actuelle. OVER() définit le cadre de fenêtre pour chaque ligne. Une clause OVER() vide indique à la base de données que l'ensemble des résultats est le cadre de la fenêtre.

Examinons un exemple de la syntaxe SUM() OVER(). Nous utiliserons la table employees de l'échantillon de données fourni par Oracle Live SQL. Cette table se compose des colonnes suivantes :

  • emp_id est l'identifiant de l'employé.
  • name est le nom de l'employé.
  • job est l'intitulé du poste.
  • dept_id est l'identifiant du service.
  • salary est le salaire de l'employé.
EMP_IDNAMEJOBDEPT_IDSALARY
7839KINGPRESIDENT105000
7698BLAKEMANAGER302850
7900JAMESCLERK30950
7934MILLERCLERK101300

Nous pouvons utiliser la fonction SUM() avec la clause OVER() pour obtenir le salaire total de tous les employés et afficher le salaire total à côté du salaire de chaque employé.

SELECT 
  emp_id, 
  name, 
  job, 
  dept_id, 
  salary, 
  SUM(salary) OVER() AS total_salary
FROM employees;
emp_idNAMEJOBDEPT_IDSALARYTOTAL_SALARY
7839KINGPRESIDENT10500029025
7698BLAKEMANAGER30285029025
7900JAMESCLERK3095029025
7934MILLERCLERK10130029025

La fonction SUM() est exécutée pour chaque ligne du tableau. Chaque fois qu'elle est appelée, elle récupère les informations salariales de toutes les lignes du tableau pour calculer le montant total du salaire. Le salaire total est affiché à côté des détails de chaque ligne. Les détails de chaque ligne sont conservés et affichés à côté du salaire total.

Dans cet exemple, le cadre de la fenêtre (l'ensemble des lignes sur lesquelles SUM() opère) est l'ensemble des données. Vous pouvez ajouter des clauses supplémentaires dans OVER() pour modifier le cadre de la fenêtre.

Exemple 1A : Calcul de la somme pour chaque groupe - SUM() avec OVER(PARTITION BY ...)

La clause OVER() peut contenir des détails sur la façon dont nous voulons partitionner les données. Nous utilisons la clause PARTITION BY dans OVER() pour diviser les données en partitions, ou groupes. L'utilisation de PARTITION BY est similaire à celle de GROUP BY dans la mesure où les lignes sont divisées en groupes sur la base de la valeur de certaines colonnes. Lorsque nous utilisons SUM() OVER(PARTITION BY …), nous pouvons calculer la somme des valeurs pour chaque groupe, ou partition, de données. Par exemple, nous pouvons calculer le salaire total pour chaque département :

SELECT 
  emp_id, 
  name, 
  job, 
  dept_id, 
  salary,
  SUM(salary) OVER(PARTITION BY dept_id) AS dept_total_salary
FROM employees;

Voici le résultat :

EMP_IDNAMEJOBDEPT_IDSALARYDEPT_TOTAL_SALARY
7782CLARKMANAGER1024508750
7934MILLERCLERK1013008750
7839KINGPRESIDENT1050008750
7902FORDANALYST20300010875
7788SCOTTANALYST20300010875
7566JONESMANAGER20297510875
7369SMITHCLERK2080010875
7876ADAMSCLERK20110010875
7521WARDSALESMAN3012509400
7654MARTINSALESMAN3012509400
7844TURNERSALESMAN3015009400
7900JAMESCLERK309509400
7499ALLENSALESMAN3016009400
7698BLAKEMANAGER3028509400

Nous utilisons SUM(salary) OVER(PARTITION BY dept_id) pour obtenir le salaire total par département. La clause PARTITION BY divise les lignes en groupes sur la base de la colonne dept_id. Les lignes dont la valeur dept_id est égale à 10 sont placées dans un groupe (marqué en jaune dans le tableau ci-dessus), les lignes dont la valeur dept_id est égale à 20 sont placées dans un autre groupe (marqué en vert), et enfin les lignes dont la valeur dept_id est égale à 30 sont placées dans un autre groupe (marqué en rouge). La fonction SUM() calcule la somme des lignes dans chaque groupe.

Notez que lorsque vous utilisez SUM() OVER(PARTITION BY), vous conservez les détails des lignes individuelles. Vous pouvez, par exemple, voir les détails de l'employé nommé Ford : son poste, son salaire et sa comparaison avec le total des salaires de son département.

C'est l'utilisation la plus typique de SUM() OVER(PARTITION BY): vous calculez la valeur de la somme pour chaque groupe de données et vous conservez les détails des lignes individuelles. Voyons un exemple similaire.

Exemple 1B : Calcul du salaire pour chaque titre de poste

Nous pouvons utiliser SUM(salary) OVER(PARTITION BY job) pour obtenir le salaire total par poste. Voyons ce que cela donne :

SELECT 
  emp_id, 
  name, 
  job, 
  dept_id, 
  salary,
  SUM(salary) OVER(PARTITION BY job) AS job_total_salary
FROM employees;

Voici le résultat :

EMP_IDNAMEJOBDEPT_IDSALARYJOB_TOTAL_SALARY
7782CLARKMANAGER1024508275
7698BLAKEMANAGER3028508275
7566JONESMANAGER2029758275
7934MILLERCLERK1013004150
7369SMITHCLERK208004150
7876ADAMSCLERK2011004150
7900JAMESCLERK309504150
7902FORDANALYST2030006000
7788SCOTTANALYST2030006000
7521WARDSALESMAN3012505600
7654MARTINSALESMAN3012505600
7844TURNERSALESMAN3015005600
7499ALLENSALESMAN3016005600
7839KINGPRESIDENT1050005000

Cette fois, les lignes sont regroupées en fonction de la valeur du poste plutôt que de l'identifiant du service. Les employés ayant la même fonction sont regroupés et nous calculons le salaire total des personnes occupant cette fonction. La fonction SUM() est appliquée à tous les salaires de chaque groupe : le salaire total du groupe "Manager" est la somme de 2450, 2850 et 2975, qui sont les salaires des trois managers figurant dans notre tableau.

Exemple 2 : calculer le rapport entre la valeur d'une seule ligne et le total

Généralement, nous voulons voir la comparaison entre chaque ligne individuelle et la somme totale. Calculons le pourcentage du salaire de chaque personne par rapport au total des salaires de son service.

SELECT 
  emp_id, 
  name, 
  job, 
  dept_id, 
  salary,
  ROUND(100.0 * salary / SUM(salary) OVER(PARTITION BY dept_id), 2) 
           AS percentage_of_dept_total_salary
FROM employees;
EMP_IDNAMEJOBDEPT_IDSALARYPERCENTAGE_OF_DEPT_TOTAL_SALARY
7782CLARKMANAGER10245028
7934MILLERCLERK10130014.86
7839KINGPRESIDENT10500057.14
7902FORDANALYST20300027.59
7788SCOTTANALYST20300027.59
7566JONESMANAGER20297527.36
7369SMITHCLERK208007.36
7876ADAMSCLERK20110010.11
7521WARDSALESMAN30125013.3
7654MARTINSALESMAN30125013.3
7844TURNERSALESMAN30150015.96
7900JAMESCLERK3095010.11
7499ALLENSALESMAN30160017.02
7698BLAKEMANAGER30285030.32

Cette fois, les lignes sont regroupées en fonction de la valeur job plutôt que de l'ID du département. Les employés occupant le même poste sont regroupés et nous calculons le salaire total des personnes occupant ce poste. La fonction SUM() est appliquée à tous les salaires de chaque groupe : le salaire total du groupe "Manager" est la somme de 2450, 2850 et 2975, qui sont les salaires des trois managers figurant dans notre tableau.

Exemple 2 : calculer le rapport entre la valeur d'une seule ligne et le total

Généralement, nous voulons voir la comparaison entre chaque ligne individuelle et la somme totale. Calculons le pourcentage du salaire de chaque personne par rapport au total des salaires de son service.

SELECT 
  emp_id, 
  name, 
  job, 
  dept_id, 
  salary,
  ROUND(100.0 * salary / SUM(salary) OVER(PARTITION BY dept_id), 2) 
           AS percentage_of_dept_total_salary
FROM employees;
EMP_IDNAMEJOBDEPT_IDSALARYPERCENTAGE_OF_DEPT_TOTAL_SALARY
7782CLARKMANAGER10245028
7934MILLERCLERK10130014.86
7839KINGPRESIDENT10500057.14
7902FORDANALYST20300027.59
7788SCOTTANALYST20300027.59
7566JONESMANAGER20297527.36
7369SMITHCLERK208007.36
7876ADAMSCLERK20110010.11
7521WARDSALESMAN30125013.3
7654MARTINSALESMAN30125013.3
7844TURNERSALESMAN30150015.96
7900JAMESCLERK3095010.11
7499ALLENSALESMAN30160017.02
7698BLAKEMANAGER30285030.32

Nous constatons, par exemple, que l'analyste Scott a un salaire individuel de 3 000, ce qui représente 27,59 % du total des salaires de son service.

Voici une ventilation des fonctions utilisées pour accomplir cette tâche :

  • Nous prenons chaque salaire individuel et le divisons par le salaire total du département :

salary / SUM(salary) OVER(PARTITION BY dept_id)

  • Pour obtenir un pourcentage, nous le multiplions par 100 % :
    • 0 * salary / SUM(salary) OVER(PARTITION BY dept_id)
  • Ensuite, nous utilisons la fonction ROUND() pour obtenir deux chiffres décimaux :

ROUND(100.0 * salary / SUM(salary) OVER(PARTITION BY dept_id), 2)

Le calcul du rapport entre la ligne individuelle et la somme pour un groupe est un autre cas d'utilisation très courant de SUM() avec OVER(PARTITION BY). De la même manière, vous pouvez calculer la différence entre le total du groupe et la ligne individuelle.

Quelle est la différence entre SUM() avec OVER(PARTITION BY …) et SUM() avec GROUP BY?

La clause PARTITION BY accomplit une tâche similaire à la clause GROUP BY. OVER(PARTITION BY) et GROUP BY divisent l'ensemble de données en partitions, ou groupes. Lors de l'utilisation de la fonction SUM(), les deux expressions calculent la somme pour chaque groupe. Alors, laquelle choisir ?

Lorsque vous utilisez la fonction GROUP BY, les détails des lignes individuelles sont réduits. Jetez un coup d'œil :

SELECT 
  job, 
  SUM(salary) AS total_salary
FROM employees
GROUP BY job;
JOBTOTAL_SALARY
ANALYST6000
CLERK4150
SALESMAN5600
MANAGER8275
PRESIDENT5000

Ici, nous obtenons la valeur salariale totale pour chaque titre de poste sans tenir compte des salaires individuels des employés.

Toutefois, si vous souhaitez comparer la valeur totale avec les valeurs des lignes individuelles (par exemple, pour calculer le rapport entre la valeur individuelle et la valeur totale), vous pouvez utiliser OVER(PARTITION BY …). Il renvoie toutes les lignes individuelles ainsi que la valeur totale pour chaque ligne. Cette valeur totale peut varier en fonction de la partition à laquelle la ligne appartient.

SELECT 
  name, 
  job, 
  salary, 
  SUM(salary) OVER(PARTITION BY job) AS total_salary
FROM employees;
NAMEJOBSALARYTOTAL_SALARY
FORDANALYST30006000
SCOTTANALYST30006000
SMITHCLERK8004150
JAMESCLERK9504150
ADAMSCLERK11004150
MILLERCLERK13004150
BLAKEMANAGER28508275
JONESMANAGER29758275
CLARKMANAGER24508275
KINGPRESIDENT50005000
TURNERSALESMAN15005600
ALLENSALESMAN16005600
WARDSALESMAN12505600
MARTINSALESMAN12505600

La valeur de total_salary correspond aux résultats de la requête précédente avec GROUP BY. Mais ici, vous pouvez également voir les salaires individuels. Par exemple, il y a deux analystes qui gagnent 6000 au total ; chacun d'entre eux gagne 3000.

La règle générale est la suivante : si vous souhaitez connaître uniquement la valeur totale de chaque groupe et que vous n'êtes pas intéressé par les détails de chaque ligne, vous devez utiliser la clause GROUP BY. Si vous êtes intéressé à la fois par la somme de chaque groupe et par le détail des lignes individuelles, vous devez utiliser SUM() OVER(PARTITION BY).

Exemple 3 : Calcul d'un total courant à l'aide de SUM() avec OVER(PARTITION BY)

Une autre utilisation courante de la syntaxe SUM() OVER(...) consiste à calculer le total courant.

Un total courant est la somme cumulative des nombres précédents dans une colonne. Les totaux courants sont utilisés pour calculer des valeurs qui s'accumulent au fil du temps. Par exemple, avec un total courant, vous pouvez calculer l'utilisation mensuelle des données mobiles en ajoutant la valeur de chaque jour suivant à la somme des valeurs des jours précédents. De même, vous pouvez calculer comment le nombre d'utilisateurs enregistrés augmente chaque jour ou comment le revenu total augmente à chaque transaction.

Nous utilisons la syntaxe SUM() avec OVER(PARTITION BY … ORDER BY …) pour calculer le total courant.

Prenons un exemple. Nous utiliserons la table orders de l'échantillon de données fourni par Oracle Live SQL. Cette table stocke les données historiques des commandes. Chaque commande a sa date (order_date), son représentant (sales_rep_id) et sa valeur totale (order_total).

Nous calculons ici la valeur totale courante pour chaque représentant commercial :

SELECT 
  order_date, 
  sales_rep_id, 
  order_total,
  SUM(order_total) OVER(PARTITION BY sales_rep_id ORDER BY order_date) 
          AS running_total
FROM orders;
ORDER_DATESALES_REP_IDORDER_TOTALRUNNING_TOTAL
29-MAR-07 02.22.40.536996 PM15310794.610794.6
16-AUG-07 03.34.12.234359 PM15378279.689074.2
04-OCT-07 09.53.34.362632 PM15312989203.2
21-NOV-07 10.22.33.263332 AM15313824103027.2
16-DEC-07 08.19.55.462332 PM15311188.5114215.7
27-JUL-06 12.22.59.662632 PM15452471.952471.9
27-JUL-06 01.34.16.562632 PM154364656117.9
29-JUN-07 09.53.41.984501 AM1544856165.9
01-JUL-07 04.49.13.615512 PM15422056385.9
02-JUL-07 03.34.44.665170 AM15460056985.9
01-SEP-07 09.53.26.934626 AM154545162436.9
02-OCT-07 05.49.34.678340 PM1546653.469090.3
10-NOV-07 03.49.25.526321 AM15450125119215.3
19-NOV-07 02.41.54.696211 PM15442283.2161498.5
17-DEC-07 05.03.52.562632 PM15410474.6171973.1

Pour ce faire, nous partitionnons notre table par représentant commercial, puis nous ordonnons chaque partition par date :

	SUM(order_total) OVER(PARTITION BY sales_rep_id ORDER BY order_date)

Le nouvel élément de syntaxe est ORDER BY. Il définit la manière dont les lignes sont triées dans chaque fenêtre. La fonction SUM() est appliquée à chaque ligne ; elle additionne la valeur actuelle de order_total à la valeur précédente de running_total; les totaux courants sont calculés séparément pour chaque partition (ici, pour chaque ID de représentant commercial).

Examinons de plus près le représentant commercial dont l'ID est 153. Sa première commande date du29 mars et sa valeur totale est de 10794,6. À ce stade, le total courant (la somme) est égal à la valeur de la commande. Leur deuxième commande a été passée le16 août pour un montant de 78279,6 ; le total courant est maintenant égal à la somme des valeurs de la première et de la deuxième commande (10794,6 + 78279,6 = 89074,2). Après leur troisième commande, le total courant est égal au total courant précédent plus la valeur de la troisième commande (89074,2 + 129 = 89203,2). Ce processus est similaire pour le représentant commercial dont l'ID est 154.

Le calcul d'un total courant est un schéma courant lors de l'utilisation de SQL pour l'analyse de données. Vous pouvez lire comment calculer un total courant en SQL ailleurs dans notre blog.

Exemple 4 : Comptage d'objets dans des catégories personnalisées

La fonction SUM() est souvent associée à l'instruction CASE WHEN pour compter les objets dans des catégories personnalisées. Par exemple, vous pouvez vouloir calculer le salaire total des employés occupant des postes de direction dans un département et l'afficher à côté des détails de chaque employé. Vous pouvez y parvenir en utilisant SUM() OVER(PARTITION BY) en combinaison avec CASE WHEN.

Examinons tout d'abord l'instruction CASE WHEN. Elle est similaire à l'instruction if utilisée dans de nombreux langages de programmation. Nous l'utilisons pour définir la valeur d'une expression dans différentes situations, ou cas.

Dans l'exemple suivant, nous utilisons l'instruction CASE WHEN pour identifier chaque employé en tant que cadre (directeurs et présidents) ou en tant qu'employé ordinaire (tous les autres postes). Jetez un coup d'œil :

SELECT 
  emp_id, 
  name, 
  job, 
  dept_id, 
  CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) 
    THEN ‘MANAGEMENT’ 
    ELSE ‘REGULAR’ END AS emp_type
  salary
FROM employees;

L'instruction CASE évalue toutes les conditions WHEN. Si elle trouve la condition correspondante, elle renvoie la valeur dans la branche THEN. Si elle ne trouve pas la condition correspondante, elle renvoie la valeur indiquée après ELSE. Dans notre exemple, les employés occupant le poste de président ou de directeur sont étiquetés comme 'Management'. Tous les autres postes se voient attribuer l'étiquette "Regular". Voici le résultat de la requête :

EMP_IDNAMEJOBDEPT_IDEMP_TYPESALARY
7782CLARKMANAGER10MANAGEMENT2450
7934MILLERCLERK10REGULAR1300
7839KINGPRESIDENT10MANAGEMENT5000
7902FORDANALYST20REGULAR3000
7788SCOTTANALYST20REGULAR3000
7566JONESMANAGER20MANAGEMENT2975
7369SMITHCLERK20REGULAR800
7876ADAMSCLERK20REGULAR1100
7521WARDSALESMAN30REGULAR1250
7654MARTINSALESMAN30REGULAR1250
7844TURNERSALESMAN30REGULAR1500
7900JAMESCLERK30REGULAR950
7499ALLENSALESMAN30REGULAR1600
7698BLAKEMANAGER30MANAGEMENT2850

Pour en savoir plus sur CASE, lisez l'article Comment utiliser CASE en SQL.

Vous pouvez également utiliser l'instruction CASE avec SUM() pour additionner des valeurs dans des catégories personnalisées. Voici la requête :

SELECT
  dept_id,
  SUM(
    CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) 
    THEN salary
    ELSE 0 END) 
    AS dept_management_salary,
  SUM(
    CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) 
    THEN 0
    ELSE salary END) 
    AS dept_regular_salary
FROM employees
GROUP BY dept_id;
DEPT_IDDEPT_MANAGEMENT_SALARYDEPT_REGULAR_SALARY
1074501300
2029757900
3028506550

Pour les employés occupant des postes de direction, la première instruction CASE renvoie la valeur de la colonne salary. La fonction SUM() combinée à GROUP BY additionne ensuite tous les salaires des cadres avec la même valeur dept_id. De cette manière, nous calculons le salaire total des cadres par département. La deuxième instruction CASE calcule le salaire total par département pour tous les employés réguliers.

Vous pouvez calculer le salaire total des employés occupant un poste de direction dans un département et l'afficher à côté des détails de l'employé en utilisant SUM() avec PARTITION BY:

SELECT 
  emp_id, 
  name, 
  job, 
  dept_id, 
  CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) 
    THEN ‘MANAGEMENT’ 
    ELSE ‘REGULAR’ END AS emp_type
  salary,
  SUM(
    CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) 
    THEN salary 
    ELSE 0 END) OVER(PARTITION BY dept_id) AS dept_management_salary
FROM employees;
EMP_IDNAMEJOBDEPT_IDEMP_TYPESALARYDEPT_MANAGEMENT_SALARY
7782CLARKMANAGER10MANAGEMENT24507450
7934MILLERCLERK10REGULAR13007450
7839KINGPRESIDENT10MANAGEMENT50007450
7902FORDANALYST20REGULAR30002975
7788SCOTTANALYST20REGULAR30002975
7566JONESMANAGER20MANAGEMENT29752975
7369SMITHCLERK20REGULAR8002975
7876ADAMSCLERK20REGULAR11002975
7521WARDSALESMAN30REGULAR12502850
7654MARTINSALESMAN30REGULAR12502850
7844TURNERSALESMAN30REGULAR15002850
7900JAMESCLERK30REGULAR9502850
7499ALLENSALESMAN30REGULAR16002850
7698BLAKEMANAGER30MANAGEMENT28502850

Les lignes sont divisées en groupes en fonction de la colonne dept_id. Il y a trois groupes, un pour chaque département. La fonction SUM() est appliquée à l'expression CASE WHEN. Au lieu de calculer le salaire total dans chaque département, nous calculons le salaire total des employés occupant des postes de direction dans le département. La fonction CASE renvoie 0 pour les employés ordinaires (la somme n'est pas augmentée) et la valeur du salaire pour les cadres. Vous pouvez utiliser ce modèle dans de nombreuses situations différentes. En fait, dans la section suivante, nous verrons un autre exemple de combinaison de CASE WHEN avec SUM() et OVER(PARTITION BY).

Exemple 5 : Calcul du total d'une commande avec des remises en utilisant SUM() avec CASE WHEN

Dans cet exemple, nous voulons calculer la valeur totale de chaque commande, y compris les remises pour certains articles de la commande. Nous utiliserons la syntaxe SUM() OVER(PARTITION BY …) pour additionner toutes les valeurs des articles par commande. Et pour intégrer les remises sur les produits, nous utiliserons l'instruction CASE WHEN.

Nous utilisons la table order_items de l'échantillon de données fourni par Oracle Live SQL. Cette table stocke tous les articles de la commande (product_id) appartenant à chaque commande (order_id). Elle contient des informations sur le prix unitaire du produit (unit_price) et la quantité commandée (quantity).

Nous voulons maintenant calculer les valeurs de la commande : une pour chaque produit de la commande et un total pour la commande ; le total de la commande doit inclure toutes les réductions appliquées aux produits.

Le total de la commande est égal au prix unitaire multiplié par la quantité commandée. Toutefois, lorsqu'une remise est appliquée à un produit, nous utiliserons un relevé CASE WHEN pour en rendre compte.

SELECT 
  order_id, 
  product_id, 
  unit_price, 
  quantity,   

  SUM(CASE 
     -- 20% discount for this product
     WHEN product_id = 3143 THEN unit_price*quantity*0.8
     -- 40% discount for this product
     WHEN product_id = 3106 THEN unit_price*quantity*0.6
     ELSE unit_price*quantity END)
  OVER(PARTITION BY order_id, product_id) 
        AS order_product_total_with_discount,

  SUM(CASE 
     -- 20% discount for this product
     WHEN product_id = 3143 THEN unit_price*quantity*0.8
     -- 40% discount for this product
     WHEN product_id = 3106 THEN unit_price*quantity*0.6
     ELSE unit_price*quantity END)
  OVER(PARTITION BY order_id) 
        AS order_total_with_discount    

FROM order_items;
ORDER_IDPRODUCT_IDUNIT_PRICEQUANTITYORDER_PRODUCT_TOTAL_WITH_DISCOUNTORDER_TOTAL_WITH_DISCOUNT
2354310648611756.844916.2
2354311496.8434162.444916.2
235431237947371344916.2
235431294147192744916.2
235431392148100844916.2
235431431653678.444916.2
23543150175898644916.2
235431633061183044916.2
235431653764236844916.2
235431675168346844916.2
23543170145.2701016444916.2
23543176113.3728157.644916.2
235431826177469744916.2
2355228946200920094513.5
23552308571851054594513.5
2355231186.918816337.294513.5
2355232219188357294513.5
2355232317190323094513.5
235523261.1192211.294513.5
235523301.1197216.794513.5
2355233925199497594513.5
23552359226.620446226.494513.5

Pour calculer le total par produit dans une commande, nous utilisons la syntaxe suivante :

SUM(CASE 
       WHEN product_id=3143 THEN unit_price*quantity*0.8 -- 20% discount 
       WHEN product_id=3106 THEN unit_price*quantity*0.6 -- 40% discount 
       ELSE unit_price*quantity END)
OVER(PARTITION BY order_id, product_id) AS order_product_total_with_discount

Nous transmettons l'instruction CASE WHEN comme argument à la fonction SUM(); si l'ID de produit de la ligne actuelle est 3143, nous appliquons une remise de 20 % ; pour l'ID de produit 3106, la remise est de 40 %. Ensuite, nous partitionnons l'ensemble de données par ID de commande et ID de produit afin d'obtenir les valeurs totales pour chaque produit d'une commande.

Notez que nous utilisons deux clauses PARTITION BY différentes dans la requête. Pour calculer la valeur totale du produit, nous partitionnons l'ensemble de données par ID de commande et ID de produit. Pour calculer la valeur totale par commande, nous partitionnons l'ensemble de données en fonction de l'identifiant de la commande uniquement. La valeur totale de la commande est égale pour toutes les lignes ayant le même ID de commande. En d'autres termes, si vous additionnez toutes les valeurs totales des produits d'une certaine commande, vous obtenez la valeur totale de la commande. Par exemple, pour l'ID de commande 2355, nous obtenons ce qui suit : 9200 + 10545 + 16337.2 + 3572 + 3230 + 211.2 + 216.7 + 4975 + 46226.4 = 94513.5.

Voici quelques exemples de la fonction SUM() avec CASE WHEN.

Aller de l'avant et utiliser la fonction SUM() avec OVER() et PARTITION BY

Maintenant que vous savez comment utiliser la fonction de fenêtre SUM() et ses différentes options syntaxiques, vous pouvez l'essayer vous-même.

Nous avons présenté des exemples sur la façon de calculer un pourcentage de la valeur d'une seule ligne par rapport au total de la partition et nous avons montré comment calculer le total courant et le total de la commande personnalisée. Nous vous encourageons à vous exercer avec vos propres données.

Pour en savoir plus, essayez notre cours interactif Fonctions de fenêtrage qui explique en détail tous les concepts des fonctions de fenêtre. Vous pouvez également consulter notre aide-mémoire Fonctions de fenêtrage si vous souhaitez une référence rapide et facile pour les fonctions de fenêtre SQL.

Bonne chance !