Chapitre 3 : Fusion de tables¶
Programme officiel (B.O.)¶
B.O. spécial n° 1 du 22 janvier 2019 - NSI Première
| Contenus | Capacités attendues | Commentaires |
|---|---|---|
| Fusion de tables | Construire une nouvelle table en combinant les données de deux tables. | La notion de clé étrangère est mise en évidence. |
1. Pourquoi fusionner des tables ?¶
1.1 Le problème de la redondance¶
Imaginons qu'on veuille stocker les résultats des élèves avec les informations de leur classe. Si on met tout dans une seule table, les informations de classe sont répétées pour chaque élève :
| Nom | Classe | Professeur principal | Salle | Note |
|---|---|---|---|---|
| Dupont | 1NSI-A | M. Duval | 204 | 15 |
| Martin | 1NSI-A | M. Duval | 204 | 12 |
| Durand | 1NSI-B | Mme Leroux | 108 | 18 |
| Petit | 1NSI-A | M. Duval | 204 | 9 |
Les informations « M. Duval » et « 204 » sont répétées trois fois. C'est de la redondance.
1.2 La solution : séparer les données¶
On sépare en deux tables reliées par un attribut commun (la clé) :
Table eleves :
| Nom | Classe | Note |
|---|---|---|
| Dupont | 1NSI-A | 15 |
| Martin | 1NSI-A | 12 |
| Durand | 1NSI-B | 18 |
| Petit | 1NSI-A | 9 |
Table classes :
| Classe | Professeur principal | Salle |
|---|---|---|
| 1NSI-A | M. Duval | 204 |
| 1NSI-B | Mme Leroux | 108 |
L'attribut Classe est présent dans les deux tables : c'est la clé de jointure. Dans la table eleves, on l'appelle clé étrangère car elle fait référence à une entrée d'une autre table.
2. La jointure¶
2.1 Principe¶
La jointure (ou fusion) consiste à combiner les lignes de deux tables qui partagent une même valeur pour un attribut commun.
Pour chaque ligne de la première table, on cherche la ligne correspondante dans la seconde table (celle qui a la même valeur de clé), et on fusionne les deux.
2.2 Exemple en Python¶
eleves = [
{"nom": "Dupont", "classe": "1NSI-A", "note": 15},
{"nom": "Martin", "classe": "1NSI-A", "note": 12},
{"nom": "Durand", "classe": "1NSI-B", "note": 18},
{"nom": "Petit", "classe": "1NSI-A", "note": 9}
]
classes = [
{"classe": "1NSI-A", "prof": "M. Duval", "salle": 204},
{"classe": "1NSI-B", "prof": "Mme Leroux", "salle": 108}
]
def jointure(table1, table2, cle):
"""Fusionne deux tables sur un attribut commun."""
resultat = []
for ligne1 in table1:
for ligne2 in table2:
if ligne1[cle] == ligne2[cle]:
fusion = {}
fusion.update(ligne1)
fusion.update(ligne2)
resultat.append(fusion)
return resultat
table_complete = jointure(eleves, classes, "classe")
for e in table_complete:
print(e)
Résultat :
{"nom": "Dupont", "classe": "1NSI-A", "note": 15, "prof": "M. Duval", "salle": 204}
{"nom": "Martin", "classe": "1NSI-A", "note": 12, "prof": "M. Duval", "salle": 204}
{"nom": "Durand", "classe": "1NSI-B", "note": 18, "prof": "Mme Leroux", "salle": 108}
{"nom": "Petit", "classe": "1NSI-A", "note": 9, "prof": "M. Duval", "salle": 204}
2.3 Fonctionnement détaillé¶
Pour chaque élève, on parcourt toutes les classes pour trouver celle qui a la même valeur de "classe". Quand on la trouve, on fusionne les deux dictionnaires :
Dupont (1NSI-A) + classe 1NSI-A (M. Duval, 204) → fusion
Martin (1NSI-A) + classe 1NSI-A (M. Duval, 204) → fusion
Durand (1NSI-B) + classe 1NSI-B (Mme Leroux, 108) → fusion
Petit (1NSI-A) + classe 1NSI-A (M. Duval, 204) → fusion
3. Cas particuliers¶
3.1 Lignes sans correspondance¶
Si un élève a une classe qui n'existe pas dans la table classes, il ne sera pas inclus dans le résultat de la jointure :
eleves = [
{"nom": "Dupont", "classe": "1NSI-A", "note": 15},
{"nom": "Moreau", "classe": "1NSI-C", "note": 14} # classe inconnue
]
# Moreau n'apparait pas dans le résultat car "1NSI-C" n'est pas dans classes
C'est le comportement standard de la jointure : seules les lignes ayant une correspondance dans les deux tables sont conservées.
3.2 Attributs en conflit¶
Si les deux tables ont un attribut de même nom (autre que la clé), la valeur de la seconde table écrase celle de la première (avec update()). Pour l'éviter, on peut renommer les attributs :
def jointure_safe(table1, table2, cle):
"""Jointure avec préfixe pour éviter les conflits."""
resultat = []
for l1 in table1:
for l2 in table2:
if l1[cle] == l2[cle]:
fusion = {}
for k, v in l1.items():
fusion[k] = v
for k, v in l2.items():
if k != cle:
fusion[k] = v
resultat.append(fusion)
return resultat
4. Clé primaire et clé étrangère¶
4.1 Clé primaire¶
Une clé primaire est un attribut (ou un ensemble d'attributs) qui identifie de manière unique chaque ligne d'une table. Aucune autre ligne ne peut avoir la même valeur.
Dans la table classes, "classe" est la clé primaire : chaque classe n'apparait qu'une seule fois.
4.2 Clé étrangère¶
Une clé étrangère est un attribut d'une table qui fait référence à la clé primaire d'une autre table.
Dans la table eleves, "classe" est une clé étrangère : elle fait référence à la clé primaire de la table classes.
Table eleves Table classes
+---------+---------+------+ +---------+------------+-------+
| nom | classe | note | | classe | prof | salle |
+---------+---------+------+ +---------+------------+-------+
| Dupont | 1NSI-A ------>| | 1NSI-A | M. Duval | 204 |
| Martin | 1NSI-A ------>| | 1NSI-B | Mme Leroux | 108 |
| Durand | 1NSI-B ------>| +---------+------------+-------+
| Petit | 1NSI-A ------>|
+---------+---------+------+
4.3 Intérêt¶
- Pas de redondance : les informations de chaque classe ne sont stockées qu'une seule fois.
- Cohérence : si le prof principal change, on ne modifie qu'une seule ligne dans
classes(et non toutes les lignes deeleves). - Organisation : les données sont séparées par thème logique.
5. Exemple complet : combiner trois tables¶
On peut enchaîner les jointures pour fusionner plus de deux tables :
eleves = [
{"id_eleve": 1, "nom": "Dupont", "id_classe": 101},
{"id_eleve": 2, "nom": "Martin", "id_classe": 101},
{"id_eleve": 3, "nom": "Durand", "id_classe": 102}
]
classes = [
{"id_classe": 101, "nom_classe": "1NSI-A", "id_prof": 201},
{"id_classe": 102, "nom_classe": "1NSI-B", "id_prof": 202}
]
professeurs = [
{"id_prof": 201, "nom_prof": "M. Duval"},
{"id_prof": 202, "nom_prof": "Mme Leroux"}
]
# Étape 1 : fusionner élèves et classes
etape1 = jointure(eleves, classes, "id_classe")
# Étape 2 : fusionner le résultat avec les professeurs
resultat = jointure(etape1, professeurs, "id_prof")
for e in resultat:
print(f"{e['nom']} - {e['nom_classe']} - {e['nom_prof']}")
# Dupont - 1NSI-A - M. Duval
# Martin - 1NSI-A - M. Duval
# Durand - 1NSI-B - Mme Leroux
6. Résumé¶
| Concept | Détail |
|---|---|
| Redondance | Répétition inutile d'informations dans une table |
| Jointure | Fusion de deux tables sur un attribut commun |
| Clé primaire | Attribut identifiant de manière unique chaque ligne |
| Clé étrangère | Attribut faisant référence à la clé primaire d'une autre table |
| Algorithme | Double boucle : pour chaque ligne de T1, chercher la correspondance dans T2 |
| Sans correspondance | Les lignes sans correspondance sont exclues du résultat |