15th Jun 2022 12 minutes de lecture 5 exemples pratiques d'utilisation de la clause ROWS BETWEEN en SQL Kateryna Koidan sql apprendre sql fonctions de fenêtrage Table des matières Clause ROWS : Syntaxe et options 5 Exemples pratiques d'utilisation de ROWS dans Fonctions de fenêtrage Exemple 1 Exemple 2 Exemple 3 Exemple 4 Cinquième exemple S'entraîner à utiliser ROWS en SQL Fonctions de fenêtrage Les fonctions de fenêtre SQL sont extrêmement utiles pour calculer des agrégations complexes comme les moyennes mobiles ou les totaux courants. La clause ROWS vous permet de spécifier des lignes pour vos calculs, ce qui permet des fenêtres encore plus sophistiquées. Voici cinq exemples pratiques d'utilisation de la clause ROWS BETWEEN en SQL. Lesfonctions de fenêtre (également appelées fonctions OVER) calculent leur résultat sur la base d'un cadre de fenêtre glissante (c'est-à-dire un ensemble de lignes). Elles sont similaires aux fonctions d'agrégation dans la mesure où vous pouvez calculer la moyenne, le total ou la valeur minimale/maximale d'un groupe de lignes. Toutefois, il existe quelques différences importantes : Les fonctions de fenêtre ne réduisent pas les lignes comme le font les fonctions d'agrégation. Ainsi, vous pouvez toujours mélanger les attributs d'une ligne individuelle avec les résultats d'une fonction de fenêtre. Les fonctions de fenêtre permettent des cadres de fenêtre coulissants, ce qui signifie que l'ensemble des lignes utilisées pour le calcul d'une fonction de fenêtre peut être différent pour chaque ligne individuelle. La syntaxe d'une fonction fenêtre est indiquée en bleu ci-dessous : SELECT , , OVER ( PARTITION BY <...> ORDER BY <...> ) FROM ; Lorsque vous utilisez une fonction fenêtre dans l'instruction SELECT, vous calculez essentiellement une autre colonne avec cette fonction : Vous commencez par spécifier une fonction (par exemple, AVG(), SUM(), ou COUNT()). Ensuite, vous utilisez le mot-clé OVER pour définir un ensemble de lignes. En option, vous pouvez : Regroupez les lignes avec PARTITION BY afin que les fonctions soient calculées dans ces groupes plutôt que dans l'ensemble des lignes. Triez les lignes dans un cadre de fenêtre en utilisant ORDER BY si l'ordre des lignes est important (par exemple, lors du calcul des totaux courants). Spécifiez la relation entre le cadre de la fenêtre et la ligne actuelle (par exemple, le cadre doit être la ligne actuelle et deux lignes précédentes, ou la ligne actuelle et toutes les lignes suivantes, etc.) Un cadre de fenêtre est défini à l'aide des clauses ROWS, RANGE et GROUPS. Dans cet article, nous nous concentrerons sur la clause ROWS et ses options. Pour en savoir plus sur les fonctions de fenêtre et la définition des cadres de fenêtre, consultez cet article contenant des exemples de fonctions de fenêtre, ce guide d'explication et, bien sûr, notre fiche de deux pages sur SQL Fonctions de fenêtrage . Clause ROWS : Syntaxe et options L'objectif de la clause ROWS est de spécifier le cadre de la fenêtre par rapport à la ligne actuelle. La syntaxe est la suivante : ROWS BETWEEN lower_bound AND upper_bound Les limites peuvent être l'une de ces cinq options : UNBOUNDED PRECEDING - Toutes les lignes avant la ligne actuelle. n PRECEDING - n rangées avant la rangée actuelle. CURRENT ROW - Juste la ligne actuelle. n FOLLOWING - n lignes après la ligne actuelle. UNBOUNDED FOLLOWING - Toutes les lignes après la ligne actuelle. Source : Aide-mémoire SQL Fonctions de fenêtrage Voici quelques éléments à garder à l'esprit lorsque vous définissez des cadres de fenêtre avec la clause ROWS: Le cadre de la fenêtre est évalué séparément dans chaque partition. L'option par défaut dépend de si vous utilisez ORDER BY: Avec ORDER BY, le cadre par défaut est RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. Sans ORDER BY, le cadre par défaut est ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING. Si l'une de vos limites est une ligne courante, vous pouvez omettre de spécifier cette limite et utiliser une version plus courte de la définition du cadre de la fenêtre : UNBOUNDED PRECEDING est identique à BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. n PRECEDING est identique à BETWEEN n PRECEDING AND CURRENT ROW. n FOLLOWING est identique à BETWEEN CURRENT ROW AND n FOLLOWING. UNBOUNDED FOLLOWING est le même que celui de BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING. Passons aux exemples pour voir comment cela fonctionne en pratique. 5 Exemples pratiques d'utilisation de ROWS dans Fonctions de fenêtrage Exemple 1 Pour commencer à utiliser la clause ROWS, nous allons utiliser le tableau suivant contenant les données de vente d'une librairie. sales record_iddaterevenue 12021-09-011515.45 22021-09-022345.35 32021-09-03903.99 42021-09-042158.55 52021-09-051819.80 Dans notre premier exemple, nous voulons ajouter une autre colonne qui indique le total des recettes depuis la première date jusqu'à la date de la ligne actuelle (c'est-à-dire le total courant). Voici la requête que nous pouvons utiliser : SELECT date, revenue, SUM(revenue) OVER ( ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) running_total FROM sales ORDER BY date; Pour calculer le total courant à l'aide d'une fonction fenêtre, nous suivons les étapes suivantes : Calcul du revenu total à l'aide de la fonction d'agrégation SUM(). Ordonner les enregistrements dans le cadre de la fenêtre par date (l'ordre par défaut est l'ordre croissant), car l'ordre des lignes est important lors du calcul d'un total courant. Spécifiez le cadre de la fenêtre en définissant la limite inférieure comme UNBOUNDED PRECEDING et la limite supérieure comme CURRENT ROW. Cela inclura toutes les lignes jusqu'à la ligne actuelle incluse. Notez que le comportement par défaut sans la clause ROWS spécifiée serait le même dans ce cas. Le cadre par défaut utilise RANGE, et non ROWS. Comme chaque jour n'apparaît qu'une seule fois dans la table, le résultat sera le même pour RANGE et ROWS. Ainsi, nous pourrions également utiliser la requête suivante pour obtenir les mêmes résultats : SELECT date, revenue, SUM(revenue) OVER ( ORDER BY date) running_sum FROM sales ORDER BY date; daterevenuerunning_total 2021-09-011515.451515.45 2021-09-022345.353860.80 2021-09-03903.994764.79 2021-09-042158.556923.34 2021-09-051819.808743.14 Comme vous le voyez, la requête a fonctionné comme prévu et nous avons obtenu le total courant dans notre troisième colonne. Le premier jour, il est égal aux ventes de ce jour - 1515,45 $ ; le deuxième jour, il est égal à la somme des ventes des premier et deuxième jours - 3860,80 $ ; à la ligne suivante, nous obtenons la somme des ventes des trois premiers jours - 4764,79 $, etc. Dans nos prochains exemples, nous verrons comment fonctionne la clause ROWS lorsque les enregistrements sont divisés en plusieurs groupes. Pour vous entraîner à définir des cadres de fenêtre, consultez ce cours interactif avec plus de 200 défis de codage. Fonctions de fenêtrage interactif avec plus de 200 défis de codage. Exemple 2 Pour les deux exemples suivants, nous allons utiliser le tableau ci-dessous. Il contient des données fictives sur la température moyenne (en °C) et les précipitations totales (en mm) dans deux villes italiennes (Rome et Florence) sur cinq jours consécutifs. weather record_iddatecitytemperatureprecipitation 1012021-09-01Rome18.57 1022021-09-01Florence17.35 1032021-09-02Rome18.020 1042021-09-02Florence17.015 1052021-09-03Rome20.112 1062021-09-03Florence19.010 1072021-09-04Rome20.20 1082021-09-04Florence19.60 1092021-09-05Rome22.50 1102021-09-05Florence20.40 Nous voulons calculer la température moyenne mobile sur trois jours séparément pour chaque ville. Pour séparer les calculs pour les deux villes, nous inclurons la clause PARTITION BY. Ensuite, lorsque nous spécifions le cadre de la fenêtre, nous considérons le jour actuel et les deux jours précédents : Notez également que nous avons placé notre fonction de fenêtre à l'intérieur de la fonction ROUND() afin que la moyenne mobile sur trois jours soit arrondie à une décimale. Voici le résultat : citydatetemperaturemov_avg_3d_city Florence2021-09-0117.317.3 Florence2021-09-0217.617.5 Florence2021-09-0319.018.0 Florence2021-09-0419.618.7 Florence2021-09-0520.419.7 Rome2021-09-0118.518.5 Rome2021-09-0219.018.8 Rome2021-09-0320.119.2 Rome2021-09-0420.219.8 Rome2021-09-0522.520.9 La moyenne mobile a été calculée séparément pour Florence et Rome. Pour le 1er septembre, la moyenne mobile est égale à la température moyenne quotidienne, car nous n'avons pas de données précédentes. Ensuite, le 2 septembre, la moyenne mobile est calculée comme la température moyenne du 1er et du 2 septembre (17,5 °C à Florence et 18,8 °C à Rome, respectivement). Le 3 septembre, nous avons enfin assez de données pour calculer la température moyenne sur trois jours (les deux précédents et le jour en cours), qui s'avère être de 18,0 °C à Florence et de 19,2 °C à Rome. Ensuite, la moyenne mobile sur trois jours du 4 septembre est calculée comme la moyenne des températures des 2, 3 et 4 septembre, et ainsi de suite. Une dernière chose à noter : l'ordre des enregistrements dans le cadre de la fenêtre joue un rôle clé dans la détermination des lignes à prendre en compte. Dans la requête ci-dessus, nous avons classé les enregistrements dans le cadre de la fenêtre par date dans l'ordre croissant (en utilisant le paramètre par défaut), c'est-à-dire que nous commençons par la date la plus ancienne. Ensuite, pour inclure deux jours avant le jour actuel dans nos calculs, nous avons fixé la limite inférieure à 2 PRECEDING. Cependant, nous pourrions obtenir exactement la même fenêtre en classant les enregistrements par ordre décroissant, puis en modifiant l'option ROWS pour inclure 2 FOLLOWING au lieu de 2 PRECEDING: SELECT city, date, temperature, ROUND(AVG(temperature) OVER ( PARTITION BY city ORDER BY date DESC ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING), 1) mov_avg_3d_city FROM weather ORDER BY city, date; Cette requête donne exactement le même résultat. Exemple 3 Dans cet exemple, nous allons calculer le total des précipitations pour les trois derniers jours (c'est-à-dire un total courant sur trois jours) séparément pour deux villes. SELECT city, date, precipitation, SUM(precipitation) OVER ( PARTITION BY city ORDER BY date ROWS 2 PRECEDING) running_total_3d_city FROM weather ORDER BY city, date; Dans cette requête, nous partitionnons à nouveau les données par ville. Nous utilisons la fonction SUM() pour calculer le niveau total de précipitations pour les trois derniers jours, y compris le jour en cours. Notez également que nous utilisons une abréviation pour définir le cadre de la fenêtre en spécifiant uniquement la limite inférieure : 2 PRECEDING. Voici le résultat de la requête ci-dessus : citydateprecipitationrunning_total_3d_city Florence2021-09-0155 Florence2021-09-021520 Florence2021-09-031030 Florence2021-09-04025 Florence2021-09-05010 Rome2021-09-0177 Rome2021-09-022027 Rome2021-09-031239 Rome2021-09-04032 Rome2021-09-05012 A partir du 3 septembre, nous obtenons un total de trois jours de précipitations à Florence : 30 mm. C'est la somme des 5 mm de précipitations du 1er septembre, des 15 mm du 2 septembre et des 10 mm du 3 septembre. Savez-vous comment nous avons obtenu le total courant de 12 mm pour Rome le 5 septembre ? Essayez de suivre les résultats dans notre tableau de sortie pour vous assurer que vous comprenez comment les fonctions de fenêtre fonctionnent avec des cadres de fenêtre spécifiques. Passons maintenant à de nouvelles données et à de nouveaux exemples. Exemple 4 Pour les deux exemples suivants, nous utiliserons les données présentées ci-dessous. Elles comprennent des informations quotidiennes sur le nombre de nouveaux abonnés sur trois réseaux sociaux : Instagram, Facebook et LinkedIn. subscribers record_iddatesocial_networknew_subscribers 112021-09-01Instagram40 122021-09-01Facebook12 132021-09-01LinkedIn5 142021-09-02Instagram67 152021-09-02Facebook23 162021-09-02LinkedIn2 172021-09-03Instagram34 182021-09-03Facebook25 192021-09-03LinkedIn10 202021-09-04Instagram85 212021-09-04Facebook28 222021-09-04LinkedIn20 Commençons par calculer les totaux courants du nombre de nouveaux abonnés séparément pour chaque réseau. En gros, pour chaque jour, nous voulons voir combien de personnes se sont abonnées depuis le début de la collecte des données jusqu'à la date de la ligne actuelle. Voici une requête SQL qui répond à cette demande : SELECT social_network, date, new_subscribers, SUM(new_subscribers) OVER ( PARTITION BY social_network ORDER BY date ROWS UNBOUNDED PRECEDING) running_total_network FROM subscribers ORDER BY social_network, date; Nous commençons par calculer le nombre total de nouveaux abonnés à l'aide de la fonction d'agrégation SUM(). Ensuite, nous utilisons la clause PARTITION BY pour effectuer des calculs séparés pour chaque réseau. Nous trions également les enregistrements par date dans l'ordre croissant (par défaut). Enfin, nous définissons le cadre de la fenêtre comme UNBOUNDED PRECEDING pour inclure tous les enregistrements jusqu'à l'enregistrement actuel. Le résultat ressemble à ceci : datesocial_networknew_subscribersrunning_total_network 2021-09-01Facebook1212 2021-09-02Facebook2335 2021-09-03Facebook2560 2021-09-04Facebook2888 2021-09-01Instagram4040 2021-09-02Instagram67107 2021-09-03Instagram34141 2021-09-04Instagram85226 2021-09-01LinkedIn55 2021-09-02LinkedIn27 2021-09-03LinkedIn1017 2021-09-04LinkedIn2037 Dans le tableau des résultats, vous pouvez voir comment le nombre de nouveaux abonnés est ajouté au total cumulé pour chaque nouvel enregistrement. Le total cumulé est calculé séparément pour chaque réseau, comme spécifié dans la fonction fenêtre. Cinquième exemple Dans notre dernier exemple, je veux montrer comment nous pouvons afficher la première et la dernière valeur d'un ensemble spécifique d'enregistrements en utilisant les fonctions de fenêtre et la clause ROWS. Cette fois, ajoutons deux colonnes à la sortie : Le nombre de nouveaux abonnés ajoutés le premier jour, et le nombre de nouveaux abonnés ajoutés le dernier jour. Avec ces informations calculées séparément pour chaque réseau social, nous pouvons voir comment les performances de chaque jour se comparent à celles du début et de la fin. Voici la requête SQL permettant d'obtenir le résultat souhaité : SELECT social_network, date, new_subscribers, FIRST_VALUE(new_subscribers) OVER( PARTITION BY social_network ORDER BY date) AS first_day, LAST_VALUE(new_subscribers) OVER( PARTITION BY social_network ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_day FROM subscribers ORDER BY social_network, date; Comme vous le voyez, nous utilisons les fonctions FIRST_VALUE() et LAST_VALUE() pour obtenir les informations sur le premier et le dernier jour, respectivement. Notez également comment nous spécifions le cadre de la fenêtre pour chacune des fonctions : Nous n'incluons pas la clause ROWS avec la fonction FIRST_VALUE() car le comportement par défaut (c'est-à-dire RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) convient à nos besoins. Cependant, nous spécifions le cadre de la fenêtre avec la fonction LAST_VALUE() car l'option par défaut utiliserait la valeur de la ligne actuelle comme dernière valeur de chaque enregistrement, ce qui n'est pas ce que nous recherchons dans cet exemple. Nous spécifions le cadre de la fenêtre comme ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING pour nous assurer que tous les enregistrements sont pris en compte. Et voici l'ensemble des résultats : datesocial_networknew_subscribersfirst_daylast_day 2021-09-01Facebook121228 2021-09-02Facebook231228 2021-09-03Facebook251228 2021-09-04Facebook281228 2021-09-01Instagram404085 2021-09-02Instagram674085 2021-09-03Instagram344085 2021-09-04Instagram854085 2021-09-01LinkedIn5520 2021-09-02LinkedIn2520 2021-09-03LinkedIn10520 2021-09-04LinkedIn20520 Comme demandé, nous avons le nombre de nouveaux abonnés le premier et le dernier jour calculé séparément pour chaque réseau social. S'entraîner à utiliser ROWS en SQL Fonctions de fenêtrage Après avoir parcouru les exemples ci-dessus, nous espérons que vous avez envie d'apprendre les fonctions de fenêtre SQL et les options ROWS de manière plus approfondie. Ce kit d'outils vous permet de spécifier un cadre de fenêtre glissante et de calculer des agrégations complexes telles que les moyennes mobiles et les totaux courants. Si vous souhaitez vous familiariser avec les fonctions de fenêtre, je vous recommande le cours interactif de LearnSQL.fr. Fonctions de fenêtrage interactif. Il vous montre comment calculer des totaux et des moyennes courantes, établir différents types de classements, étudier les tendances dans le temps, etc. Mieux encore, vous ferez les exercices vous-même, ce qui est la meilleure façon d'apprendre. Si vous voulez vraiment maîtriser l'utilisation de SQL pour l'analyse de données, notre SQL avancé parcours d'apprentissage comprend également Les extensions GROUP BY en SQL et les expressions de table communes (CTE). C'est un excellent moyen d'approfondir vos connaissances des fonctions de fenêtre. Vous voulez commencer par lire un peu ? Voici les 8 principaux articles traitant des fonctions de fenêtre SQL. Merci de votre lecture et bon apprentissage. Tags: sql apprendre sql fonctions de fenêtrage