From 07474173190deef28f2e359ca287e8e5dce4909e Mon Sep 17 00:00:00 2001 From: medina5 Date: Thu, 4 Sep 2025 07:37:37 +0200 Subject: [PATCH] Views --- Home.md | 1 + Jointure.md | 29 ++++++++++--------- View.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ aggregation.md | 71 +++++++++++++++++++++++++++++++++++------------ sousrequete.md | 16 ++++++++++- window.md | 23 ++++++++++++++++ 6 files changed, 184 insertions(+), 31 deletions(-) create mode 100644 View.md diff --git a/Home.md b/Home.md index 1bebe82..cfc6997 100644 --- a/Home.md +++ b/Home.md @@ -3,6 +3,7 @@ - [Fonctions d'agrégation](aggregation.md) - [Jointure](Jointures.md) - [Sous requêtes](sousrequete.md) +- [Vues et fonctions](View.md) - [Fonctions de fenêtrage](window.md) - [Données spatiales](Spatial.md) - [Arbres](Arbres.md) diff --git a/Jointure.md b/Jointure.md index 219098f..cff9ac5 100644 --- a/Jointure.md +++ b/Jointure.md @@ -104,11 +104,14 @@ WHERE gauche IS NULL; Lister les articles dont la famille n'existe pas. ```sql -select a.* from article a -left join famille f on f.code = a.famille_code -where f.code is null +select * from article +left join famille on famille.code = article.famille_code +where famille.code is null ``` +Attention ! La valeur `null` ne peut être comparée à rien. L'égalité avec null retourne ni vrai ni faux mais null. Ainsi null n'est pas égal à null. Pour la comparaison avec null il faut utiliser les mots-clés `is` ou `is not`. + + ## Jointure croisée ou produit cartésien La jointure croisée renvoie le produit cartésien des deux tables. Chaque ligne de la première table est combinée avec chaque ligne de la deuxième table. Cela produit un très grand nombre de lignes de résultat. @@ -197,17 +200,19 @@ Avantages : ```sql -select a.* from article a -where not exists (select 1 from famille where a.famille_code = famille.code) +select * from article +where not exists ( + select 1 from famille + where a.famille_code = famille.code +) ``` ```sql -SELECT g.* -FROM gauche g -WHERE g.id NOT IN ( - SELECT d.g_id - FROM droite d -); +select * from article +where famille_code not in ( + select code from famille + where code = article.famille_code +) ``` Cette requête est elle aussi équivalente cependant il existe un risque de mauvaise interprétation. Si le sous-select contient au moins un NULL, alors toutes les lignes sont rejetées (car la comparaison avec la valeur NULL dans id NOT IN ( …, NULL, … ) est indéterminée.) @@ -241,5 +246,3 @@ join adherent b on a.nom = b.nom and a.naissance = b.naissance and a.id <> b.id ``` - -## Lateral diff --git a/View.md b/View.md new file mode 100644 index 0000000..98d9331 --- /dev/null +++ b/View.md @@ -0,0 +1,75 @@ +# Les vues + +> Une vue est une requête SQL enregistrée dans la base de données et exposée **comme une table virtuelle**. + +Elle n’enregistre pas physiquement les données, mais seulement **la définition** de la requête. + +```sql +create view ticket_complet as +select t.id, t.adherent_id, t.date_ticket, + t.mode_rglt, round(sum(prix_unitaire * quantite),2) as montant +from ticket t +join ligne l on l.ticket_id = t.id +group by t.id +``` + +# Les vues matérialisées + +> Une vue matérialisée est semblable à une vue, mais elle stocke physiquement sur le disque le résultat de la requête. + +Cela améliore les performances pour des calculs lourds mais nécessite une actualisation quand les données sources changent. + +```sql +create materialized view ticket_completZ as +select t.id, t.adherent_id, t.date_ticket, + t.mode_rglt, round(sum(prix_unitaire * quantite),2) as montant +from ticket t +join ligne l on l.ticket_id = t.id +group by t.id +``` + +Actualisation des données de la vue matérialisée. + +```sql +REFRESH MATERIALIZED VIEW ticket_completZ; +``` + +Comme sur les tables il est possible de créer des index sur les colonnes des vues matérialisées pour accélerer encore les tris. + +# les fonctions + +> Une fonction stockée est un bloc de code SQL (ou éventuellement un autre langage de programmation) qui retourne une valeur. +On l’utilise pour encapsuler une logique métier. + +Les caractères `$$` delimitent le bloc de code. Ils permetent de savoir où commence le code de la fonction et où il s'arrête. + +## Les fonctions scalaires + +C'est le cas le plus simple : la fonction retourne une seule valeur (comme un nombre, du texte, une date, un booléen, etc.). + +## Les fonctions table + +```sql +create or replace function f_dernier_ticket(adherent_id_param int) +returns table (id int, adherent_id int, + date_ticket timestamp, mode_rglt int, + montant numeric, n int) +as $$ + select * from ( + select *, + row_number() OVER ( order by tc.date_ticket desc ) as n + from ticket_completz tc + where adherent_id = adherent_id_param +) where n = 1 +$$ language sql; +``` + +## Les fonctions + +## Les procédures stockées + +les procédures stockées sont proches des fonctions mais : + +- Elles ne retournent pas de valeur directement. +- Elles peuvent exécuter des transactions (COMMIT, ROLLBACK). +- Elles servent à automatiser des traitements plus larges et plus complexes (chargements de données, batchs). diff --git a/aggregation.md b/aggregation.md index 08aa003..94683c7 100644 --- a/aggregation.md +++ b/aggregation.md @@ -12,19 +12,21 @@ select count(*) from adherent; On peut compter sur n'importe quelle colonne, dans ce cas, pour ne pas avoir à choisir on utilise le caractère joker *. -En ajoutant le mot clé `distinct` l'opération s'effectue sur les valeurs uniques d'une ou de plusieurs colonnes. +En ajoutant le mot clé `distinct` l'opération s'effectue sur les **valeurs uniques** d'une ou de plusieurs colonnes. ```sql select count(distinct codepostal) from adherent; ``` +Attention ! `count(codepostal)` compte toute les lignes, soit le nombre total d'ahérent. + #### Filtre -Il est également possible d'ajouter une condition `where` à cette colonne uniquement. C’est souvent plus lisible et performant que de faire un CASE WHEN imbriqué. +Il est également possible d'ajouter une condition `where` à cette colonne uniquement. C’est souvent plus lisible et performant que de faire un `CASE WHEN` imbriqué. ```sql select count(distinct client) filter (where produit = 'pomme') - from vente; + from ligne; ``` ### Somme @@ -128,16 +130,10 @@ having count(t.id) = 72; Avec postgreSQL et Microsoft SQL Server il n'est pas possible d'utiliser l'alias dans la condition having. La clause having intervient en amont du select dans le moteur d'exécution, l'alias n'est pas encore connu. Il faut réécrire la formule. -## Agrégats d'intervalles - -postgreSQL support un type particulier que sont les intervalles de valeur en définitissant dans un même champ une borne inférieure et une supérieure. - -`range_agg` fusionne les intervalles tandis que `range_intersect_agg` retourne l'intersection. - ## Agrégats statistiques -Les aggrégats statistiques fonctionnent suivant 2 modes soit sur la pouplation totale (POP) soit sur des échantillons (SAMP) restreints. +Les aggrégats statistiques fonctionnent suivant 2 modes soit sur la pouplation totale (**POP**) soit sur des échantillons (**SAMP**) restreints. ### Variance et écart type @@ -159,7 +155,7 @@ la fonction `corr` calcule le oefficient de corrélation linéaire de Pearson. ### Médiane et percentiles ```sql -PERCENTILE_CONT(fraction) WITHIN GROUP (ORDER BY expr) +percentile_cont(fraction) within group (order by expr) ``` Calcule le quantile de manière continue (avec une interpolation des valeurs si besoin). @@ -179,15 +175,15 @@ MODE() WITHIN GROUP (ORDER BY expr) Retourne la valeur la plus fréquente. -# Rang +## Rang `rank`, `percent_rank` et `dense_rank` calcule le rang de la données. `cume_dist` calcule la distribution cumulée. -Ces fonctions sont en réalité des fenêtres analytiques mais peuvent être utilisées pour explorer la distribution. Exemple pour répartir en quartiles +Ces fonctions sont en réalité des [fenêtres analytiques](window.md) mais peuvent être utilisées pour explorer la distribution. -# Régressions linéaires simples +## Régressions linéaires simples Ces fonctions permettent de réaliser des régressions linéaires simples directement en SQL, c’est-à-dire d’ajuster une droite de tendance entre deux ensembles de données numériques (variables x et y). @@ -200,11 +196,44 @@ La régression linéaire simple cherche une droite : y = a⋅x + b - a est la pente (slope). - b est l’ordonnée à l’origine (intercept), -`REGR_SLOPE(y, x)` Calcule la pente de la droite (a), REGR_INTERCEPT(y, x) Calcule l’ordonnée à l’origine (b). + + + + + + + + + + + + + + + + + + + + + + + + -REGR_COUNT(y, x) Nombre de paires (x, y) effectivement utilisées (hors NULL). Équivalent à COUNT(*) mais appliqué seulement sur les deux colonnes non nulles. -REGR_R2(y, x) Coefficient de détermination (entre 0 et 1). +`REGR_SLOPE(y, x)` Calcule la pente de la droite (a), + +`REGR_INTERCEPT(y, x)` Calcule l’ordonnée à l’origine (b). + +`REGR_R2(y, x)` Coefficient de détermination (entre 0 et 1). Mesure la qualité de l’ajustement : @@ -212,3 +241,11 @@ Mesure la qualité de l’ajustement : - 0 : aucun lien linéaire, plus c’est proche de 1, plus la droite est pertinente. + +`REGR_COUNT(y, x)` Nombre de paires (x, y) effectivement utilisées (hors NULL) pour effectuer le calcul. Équivalent à COUNT(*) mais appliqué seulement sur les deux colonnes non nulles. + +## Agrégats d'intervalles + +postgreSQL support un type particulier que sont les [intervalles de valeur](intervalle.md) en définitissant dans un même champ une borne inférieure et une supérieure. + +`range_agg` fusionne les intervalles tandis que `range_intersect_agg` retourne l'intersection. diff --git a/sousrequete.md b/sousrequete.md index e714da9..40225cb 100644 --- a/sousrequete.md +++ b/sousrequete.md @@ -18,9 +18,16 @@ Parce qu’elle doit produire une table (un jeu de résultats) indépendante **a - Dans le SELECT, une sous-requête peut être corrélée (elle utilise des colonnes de la requête principale) ou non. - Dans le WHERE, idem : elle peut être corrélée (EXISTS, IN dépendant de la ligne en cours) ou non (test fixe). +```sql +select * from article a1 where prix > ( + select avg(prix) from article + where famille_code = a1.famille_code +) +``` + ## Sous-requête scalaire -une sous-requête scalaire est une sous-requête qui retourne une seule valeur (un scalaire, c’est-à-dire une seule ligne et une seule colonne). +> une sous-requête scalaire est une sous-requête qui retourne **une seule valeur** (un scalaire, c’est-à-dire une seule ligne et une seule colonne). Elle peut être utilisée partout où une valeur simple est attendue, par exemple : @@ -39,6 +46,13 @@ WHERE nom_colonne = ( ) ``` +Sélection des articles dont le prix est supérieur à la moyenne des prix de tous les articles + +```sql +select * from article + where prix > (select avg(prix) from article); +``` + ## Conditions ### Exists diff --git a/window.md b/window.md index c8f4ffb..4ee9aeb 100644 --- a/window.md +++ b/window.md @@ -203,3 +203,26 @@ n lignes/valeurs après la ligne courante #### unbouded following jusqu’à la fin de la partition + + +## Exercices + +```sql +select * , +lag(total) over (order by mois) as total_mois_p, +total - lag(total) over (order by mois) as difference, +lag(total, 12) over (order by mois) as total_annee_p +from ca_mensuel +order by mois +``` + +### Moyenne glissante sur 3 mois + +```sql +select *, round(AVG(total) over ( + order by mois + rows between 2 preceding and current row +), 2) as moyenne_glissante_3 +from ca_mensuel +order by mois +```