jointure

2025-09-07 09:09:16 +02:00
parent 0f18a2c9a1
commit 60c427d3ae
4 changed files with 64 additions and 7 deletions

@@ -101,12 +101,13 @@ WHERE gauche IS NULL;
```
![](jointures/rightantijoin.svg)
Lister les articles dont la famille n'existe pas.
**Exercice :** Lister les articles dont la famille n'existe pas.
```sql
select * from article
left join famille on famille.code = article.famille_code
where famille.code is null
>> MENMA Plant Menthe Pomme
```
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`.
@@ -198,6 +199,7 @@ Avantages :
- Robuste face aux valeurs NULL (pas dambiguïté).
- Souvent optimisé par le moteur en anti-semi-join (cest-à-dire que le moteur ne lit pas plus de lignes que nécessaire dans la table de droite). Les jointures qui passent par des produits cartésiens sont consommatrices en ressources.
**Exercice :** Lister les articles dont la famille n'existe pas.
```sql
select * from article
@@ -207,6 +209,8 @@ where not exists (
)
```
Ou avec l'opérateur `not in`
```sql
select * from article
where famille_code not in (
@@ -215,7 +219,7 @@ where famille_code not in (
)
```
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.)
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 code NOT IN ( …, NULL, … ) est indéterminée.)
Il existe plusieurs syntaxes permettant dobtenir le même résultat. Toutefois, certains points méritent dêtre pris en compte :
- **Consommation de ressources** : un même résultat peut être produit par des requêtes dont le coût en temps dexécution ou en mémoire diffère sensiblement.

@@ -15,9 +15,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 *.
**Exercice :** Compter le nombre d'articles de la famille 02CHOU.
```sql
select count(*) from article
where famille_code = '02CHOU'
>> 29
```
### distinct
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.select codepostal,
count(case when genre = 1 then 1 end) as nb_hommes,
count(case when genre = 2 then 1 end) as nb_femmes
from adherent
group by codepostal;
**Exercice :** Afficher le nombre de codes postaux différents trouvés dans la table adhérent.

@@ -18,13 +18,44 @@ Parce quelle 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).
**Exercice : ** Sélectionner les articles dont le prix est supérieur à la moyenne générale des prix des articles.
Dans un langage procédural on utiliserait deux étapes pour obtenir le résultat. Première étape calculer la moyenne des prix
```sql
select * from article a1 where prix > (
select avg(prix) from article
>> 5.8060418562329390
```
Puis dans un deuxième temps faire la requête de sélection avec la valeur trouvée.
```sql
select * from article where prix > 5.8060418562329390
```
Il est possible d'utiliser une sous requête à l'intérieur de la requête principale. La sous requête calcule la moyenne à l'endroit nécessaire.
```sql
select * from article
where prix > (select avg(prix) from article);
```
**Exercice : ** Sélectionner les articles dont le prix est supérieur à la moyenne des prix des articles de la même famille.
Cette fois ci il faut calculer les moyennes des prix pour chacune des familles et comparer les articles avec la moyenne correspondante. Ce n'est plus possible en programmation procédurale.
La sous requête permet de calculer pour chaque ligne d'article la moyenne correspondante à la famille du dit article.
```sql
select code, article, prix from article a1
where prix > (
select avg(prix) from article
where famille_code = a1.famille_code
)
)
```
Remarquez l'utilisation de l'alias `a1` sur la table de la requête principale pour pouvoir être injecter sans confusion dans la sous requête car celle-ci utilise la même table.
## Sous-requête scalaire
> une sous-requête scalaire est une sous-requête qui retourne **une seule valeur** (un scalaire, cest-à-dire une seule ligne et une seule colonne).

@@ -129,6 +129,16 @@ ORDER BY est obligatoire lorsque LEAD() est utilisé. La séquence des lignes do
column_2 est la colonne qui défini l'ordre des lignes lors de la récupération de la valeur suivante. Vous pouvez spécifier plus d'une colonne.
**Exercice :** Afficher le chiffre d'affaire mensuel pour chaque mois, puis dans une deuxième colonne le chiffre d'affaire du mois précédent
```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
```
#### première valeur