Regroupements et fonctions de fenĂȘtrage dans Oracle

Bonjour, Habr! Dans l'entreprise oĂč je travaille, des rencontres ont souvent lieu (excusez-moi pour mon pote). L'un de ceux-ci comportait une confĂ©rence d'un de mes collĂšgues sur Oracle Windowing and Grouping. Ce sujet m'a semblĂ© digne d'ĂȘtre publiĂ©.







DĂšs le dĂ©but, je tiens Ă  prĂ©ciser que dans ce cas, Oracle est prĂ©sentĂ© comme un langage SQL collectif. Les regroupements et la maniĂšre dont ils sont appliquĂ©s s'appliquent Ă  toute la famille de SQL (qui est compris ici comme un langage de requĂȘte structurĂ©) et est applicable Ă  toutes les requĂȘtes avec des corrections pour la syntaxe de chaque langage.



Je vais essayer d'expliquer briÚvement et facilement toutes les informations nécessaires en deux parties. Le message sera trÚs probablement utile pour les développeurs novices. Qui s'en soucie - bienvenue au chat.



Partie 1: Offres Trier par, Grouper par, Ayant



Ici, nous allons parler de tri - Trier par, regrouper - Regrouper par, filtrer - Avoir et plan de requĂȘte. Mais tout d'abord.



Commandé par



L'opĂ©rateur Order by trie les valeurs de sortie, c'est-Ă -dire trie la valeur rĂ©cupĂ©rĂ©e par une colonne spĂ©cifique. Le tri peut Ă©galement ĂȘtre appliquĂ© par un alias de colonne dĂ©fini Ă  l'aide d'un opĂ©rateur.



L'avantage de Order by est qu'il peut ĂȘtre appliquĂ© aux colonnes numĂ©riques et chaĂźnes. Les colonnes de chaĂźnes sont gĂ©nĂ©ralement triĂ©es par ordre alphabĂ©tique.



Le tri croissant est appliqué par défaut. Si vous souhaitez trier les colonnes par ordre décroissant, utilisez l'opérateur DESC supplémentaire.



Syntaxe:



SELECT colonne1, colonne2, 
 (indique le nom)

FROM nom_table

ORDER BY colonne1, colonne2 
 ASC | DESC ;



Regardons tout avec des exemples:





Dans le premier tableau, nous récupérons toutes les données et les trions par ordre croissant selon la colonne ID.



Dans le second, nous récupérons également toutes les données. Trier par la colonne ID dans l'ordre décroissant à l'aide du mot-clé DESC .



La troisiĂšme table utilise plusieurs champs de tri. Vient d'abord le tri par dĂ©partement. Si le premier opĂ©rateur est Ă©gal pour les champs du mĂȘme dĂ©partement, la deuxiĂšme condition de tri est appliquĂ©e; dans notre cas, c'est le salaire.



C'est assez simple. Nous pouvons définir plus d'une condition de tri, ce qui nous permet de trier les listes de sortie plus intelligemment.



Par groupe



En SQL, la clause Group by collecte les donnĂ©es extraites d'une base de donnĂ©es dans des groupes spĂ©cifiques. Le regroupement divise toutes les donnĂ©es en ensembles logiques afin que les calculs statistiques puissent ĂȘtre effectuĂ©s sĂ©parĂ©ment dans chaque groupe.



Cet opérateur permet de combiner les résultats d'une sélection par une ou plusieurs colonnes. AprÚs le regroupement, il n'y aura qu'une seule entrée pour chaque valeur utilisée dans la colonne.



L'utilisation de l'instruction SQL Group by est étroitement liée à l'utilisation des fonctions d'agrégation et de l'instruction SQL Have. Une fonction d'agrégation en SQL est une fonction qui renvoie une valeur unique sur un ensemble de valeurs de colonne. Par exemple: COUNT (), MIN (), MAX (), AVG (), SUM ()



Syntaxe:



SELECT nom_colonne (s)

FROM nom_table

WHERE condition

GROUP BY nom (s) colonne (s)

ORDER BY nom (s) colonne;



Group by apparaĂźt aprĂšs la clause WHERE conditionnelle dans la requĂȘte SELECT . Vous pouvez Ă©ventuellement utiliser ORDER BY pour trier les valeurs de sortie.



Donc, sur la base du tableau de l'exemple précédent, nous devons trouver le salaire maximum des employés de chaque département. L'échantillon final doit inclure le nom du département et le salaire maximum.



Solution 1 (sans utiliser le regroupement):



SELECT DISTINCT
    ie.department
    ie.slary
    FROM itx_employee ie
    WHERE ie.salary = (
             SELECT
             max(ie1.salary)
             FROM itx_employee ie1
             WHERE ie.department = ie1.department
             )


Solution 2 (en utilisant le regroupement):



SELECT
department,
max(salary)
FROM itx_employee
GROUP BY department


Dans le premier exemple, nous résolvons le problÚme sans utiliser de regroupement, mais en utilisant une sous-sélection, i.e. mettez le second dans une sélection. Dans la deuxiÚme solution, nous utilisons le regroupement.



Le deuxiĂšme exemple est plus court et plus lisible, bien qu'il remplisse les mĂȘmes fonctions que le premier.



Comment Group by fonctionne pour nous: commence par diviser deux départements en groupes QA et dev. Ensuite, il cherche le salaire maximum pour chacun d'eux.



Ayant



Avoir est un outil de filtrage. Il indique le rĂ©sultat de l'exĂ©cution des fonctions d'agrĂ©gation. La clause Have est utilisĂ©e dans SQL oĂč WHERE ne peut pas ĂȘtre utilisĂ©.



Si la clause WHERE définit un prédicat pour filtrer les lignes, alors Have est utilisé aprÚs le regroupement pour définir un prédicat logique qui filtre le groupe en fonction des valeurs des fonctions d'agrégation. La clause est nécessaire pour tester les valeurs obtenues à l'aide de fonctions d'agrégation à partir de groupes de lignes.



Syntaxe:



SELECT nom_colonne (s)

FROM nom_table

WHERE condition

GROUP BY nom (s) colonne (s)

HAVING condition



Tout d'abord, nous affichons les départements avec un salaire moyen supérieur à 4000. Ensuite, nous affichons le salaire maximum par filtrage.



Solution 1 (sans utiliser GROUP BY et HAVING):



SELECT DISTINCT
ie.department AS "DEPARTMENT",
(
     (SELECT
     AVG(ie1.salary)
     FROM itx_employee ie1
     WHERE ie1.department = ie.department)
) AS "AVG SALARY"

FROM itx_employee ie
where (SELECT
     AVG(ie1.salary)
     FROM itx_employee ie1
     WHERE ie1.department = ie.department) > 4000




Solution 2 (en utilisant GROUP BY et HAVING):



SELECT
department, 
AVG(salary)

FROM itx_employee 
GROUP BY department
HAVING AVG(salary) > 4000




Le premier exemple utilise deux sous-sélections, l'une pour trouver le salaire maximum et l'autre pour filtrer le salaire moyen. Le deuxiÚme exemple, encore une fois, est beaucoup plus simple et concis.



Demande de plan



Il arrive souvent qu'une requĂȘte s'exĂ©cute pendant une longue pĂ©riode, consommant d'importantes ressources de mĂ©moire et de disques. Pour comprendre pourquoi une requĂȘte est longue et inefficace, nous pouvons examiner le plan de requĂȘte.



Un plan de requĂȘte est le plan d'exĂ©cution prĂ©vu pour une requĂȘte, c'est-Ă -dire comment le SGBD l'exĂ©cutera. Le SGBD notera toutes les opĂ©rations qui seront effectuĂ©es dans la sous-requĂȘte. AprĂšs avoir tout analysĂ©, nous serons en mesure de comprendre oĂč se trouvent les faiblesses de la requĂȘte et en utilisant le plan de requĂȘte, nous pouvons les optimiser.



L'exĂ©cution de toute instruction SQL dans Oracle rĂ©cupĂšre ce que l'on appelle le "plan d'exĂ©cution". Ce plan d'exĂ©cution de requĂȘte est une description de la maniĂšre dont Oracle va extraire les donnĂ©es en fonction de l'instruction SQL en cours d'exĂ©cution. Un plan est un arbre qui contient l'ordre des Ă©tapes et la relation entre elles.



Les outils qui vous permettent d'obtenir le plan d'exĂ©cution estimĂ© d'une requĂȘte sont Toad, SQL Navigator, PL / SQL Developer , etc. Ils donnent un certain nombre d'indicateurs de la consommation de ressources d'une requĂȘte, parmi lesquels les principaux sont: coĂ»t - coĂ»t d'exĂ©cution et cardinalitĂ© (ou lignes ) - cardinalitĂ© (ou quantitĂ©) lignes).



Plus la valeur de ces indicateurs est Ă©levĂ©e, moins la requĂȘte est efficace.



Ci-dessous vous pouvez voir l'analyse du plan de requĂȘte. La premiĂšre solution utilise une sous-sĂ©lection, la seconde utilise un regroupement. Notez que la premiĂšre solution a traitĂ© 22 lignes, la seconde en a traitĂ© 15.



Analyse du plan de requĂȘte:







Une autre analyse du plan de requĂȘte qui utilise deux sous-sĂ©lections:





Cet exemple est prĂ©sentĂ© comme une variante d'utilisation inefficace des outils SQL et je ne vous recommande pas de l'utiliser dans vos requĂȘtes.



Toutes les fonctionnalitĂ©s ci-dessus vous faciliteront la vie lors de l'Ă©criture de requĂȘtes et augmenteront la qualitĂ© et la lisibilitĂ© de votre code.



Partie 2: Fonctions de la fenĂȘtre



Les fonctions de fenĂȘtre remontent Ă  Microsoft SQL Server 2005. Elles effectuent des calculs sur une plage de lignes donnĂ©e dans une clause Select. En bref, une "fenĂȘtre" est un ensemble de lignes Ă  l'intĂ©rieur desquelles un calcul a lieu. "Window" vous permet de rĂ©duire les donnĂ©es et de mieux les traiter. Cette fonctionnalitĂ© vous permet de diviser l'ensemble de donnĂ©es en fenĂȘtres.



Le fenĂȘtrage a un Ă©norme avantage. Il n'est pas nĂ©cessaire de crĂ©er un ensemble de donnĂ©es pour les calculs, ce qui vous permet d'enregistrer toutes les lignes de l'ensemble avec leur ID unique. Le rĂ©sultat des fonctions de fenĂȘtre est ajoutĂ© Ă  la sĂ©lection rĂ©sultante dans un autre champ.



Syntaxe:



SELECT nom_colonne (s)

Fonction d'agrégation (colonne pour les calculs)

OVER ([ PARTITION BYcolonne Ă  grouper]

FROM nom_table

[ ORDER BY colonne Ă  trier]

[ expression ROWS ou RANGE pour restreindre les lignes dans un groupe])



OVER PARTITION BY est une propriĂ©tĂ© permettant de dĂ©finir la taille de la fenĂȘtre. Ici, vous pouvez spĂ©cifier des informations supplĂ©mentaires, donner des commandes de service, par exemple, ajouter un numĂ©ro de ligne. La syntaxe de la fonction de fenĂȘtre s'intĂšgre parfaitement dans la sĂ©lection de colonne.



Regardons tout avec un exemple: un autre département a été ajouté à notre tableau, il y a maintenant 15 lignes dans le tableau. Nous essaierons de retirer les employés, leur salaire, ainsi que le salaire maximum de l'organisation.





Dans le premier champ, nous prenons le nom, dans le second - le salaire. Ensuite, nous utilisons la fonction window sur ()... Nous l'utilisons pour obtenir le salaire maximum dans toute l'organisation, car la taille de la «fenĂȘtre» n'est pas indiquĂ©e. Over () avec des parenthĂšses vides s'applique Ă  toute la sĂ©lection. Par consĂ©quent, partout le salaire maximum est de 10 000. Le rĂ©sultat de l'action de la fonction fenĂȘtre est ajoutĂ© Ă  chaque ligne.



Si nous supprimons la mention de la fonction de fenĂȘtre de la quatriĂšme ligne de la requĂȘte, c'est-Ă -dire seul le max (salaire) reste , la demande ne fonctionnera pas. Le salaire maximum ne pouvait tout simplement pas ĂȘtre calculĂ©. Étant donnĂ© que les donnĂ©es seraient traitĂ©es ligne par ligne et qu'au moment de l'appel de max (salaire), il n'y aurait qu'un seul numĂ©ro dans la ligne courante, c'est-Ă -dire employĂ© actuel. C'est ici que vous pouvez voir l'avantage de la fonction de fenĂȘtre. Au moment de l'appel, il fonctionne avec toute la fenĂȘtre et avec toutes les donnĂ©es disponibles.



Regardons un autre exemple oĂč vous devez afficher le salaire maximum de chaque dĂ©partement:







En fait, nous dĂ©finissons le cadre de la "fenĂȘtre", en le divisant en dĂ©partements. Nous utilisons le dĂ©partement comme exemple de classement. Nous avons trois dĂ©partements: dev, qa et ventes.



"Window" trouve le salaire maximum pour chaque dĂ©partement. À la suite de la sĂ©lection, nous voyons qu'il a trouvĂ© le salaire maximum d'abord pour dev, puis pour qa, puis pour les ventes. Comme mentionnĂ© ci-dessus, le rĂ©sultat de la fonction de fenĂȘtre est Ă©crit dans le rĂ©sultat de l'extraction de chaque ligne.



Dans l'exemple prĂ©cĂ©dent, les parenthĂšses aprĂšs over n'Ă©taient pas spĂ©cifiĂ©es. Ici, nous avons utilisĂ© PARTITION BY, ce qui nous a permis de dĂ©finir la taille de notre fenĂȘtre. Ici, vous pouvez spĂ©cifier des informations supplĂ©mentaires, envoyer des commandes de service, par exemple, le numĂ©ro de ligne.



Conclusion



SQL n'est pas aussi simple qu'il y paraĂźt Ă  premiĂšre vue. Tout ce qui est dĂ©crit ci-dessus est la fonctionnalitĂ© de base des fonctions de fenĂȘtre. Avec leur aide, vous pouvez «simplifier» nos demandes. Mais il y a beaucoup plus de potentiel cachĂ© en eux: il y a des opĂ©rateurs utilitaires (par exemple ROWS ou RANGE) qui peuvent ĂȘtre combinĂ©s pour ajouter plus de fonctionnalitĂ©s aux requĂȘtes.



J'espÚre que l'article a été utile à tous ceux qui s'intéressent à ce sujet.



All Articles