Données SQL Join

Identification

Infoforall

25 - SQL : JOIN ON


Prerequis : l'activité précédente sur SQL.

Logiciel nécessaire : DB Brownser

Fichier SQLite : la base de données est à télécharger. Si vous n'avez pas de compte, vous pouvez me contacter avec le bouton en bas de page.

Documents de cours : open document ou pdf

1 - Principe de la jointure

Pour l'instant, nous n'avons travaillé qu'avec une relation à la fois.

Mais nous avions vu avec l'exercice sur les jeux vidéos retro qu'il était possible de stocker les informations sur les jeux dans une relation jeu et stocker les informations sur les consoles dans une relation console.

Voici nos deux tables :

La clé étrangère permet de faire le lien  entre la table jeu et la table console

01° Est-il nécessaire que les valeurs de l'attribut id de la relation jeu (la première "colonne" à gauche) soient toutes différentes ? Quelle contrainte doit respecter cet attribut ?

La clé étrangère permet de faire le lien  entre la table jeu et la table console

...CORRECTION...

Oui : nous avions vu qu' s'agit de la clé primaire de la relation. Chaque valeur doit être unique pour identifier à coup sûr l'un des nuplets.

Il s'agit de la contrainte d'intégrité d'UNICITE.

02° Est-il nécessaire que les valeurs de l'attribut id_support de la relation jeu (la dernière "colonne" de la table) ne soient pas toutes différentes ? Quelle contrainte doit respectée cet attribut ?

La clé étrangère permet de faire le lien  entre la table jeu et la table console

Comment se nomme l'attribut id de la relation console ? Peut-on avoir deux fois la même valeur cette fois ?

...CORRECTION...

Non, on peut avoir plusieurs fois la même valeur : id_support est juste un attribut servant de clé étrangère.

Par contre, chaque valeur doit correspondre à une valeur disponible en tant que clé primaire dans une autre table, ou NULL.

Il s'agit de la contrainte d'intégrité de REFERENCE.

Nous avons deux tables mais nous voudrions créer un affichage ressemblant à ceci pour notre site Web parlant de jeux vidéo retro de types plateformes : on veut filter uniquement les jeux de plateformes mais obtenir un seul "tableau".

On rajoute les infos sur la console en plus des infos sur le jeu lui-même

Le principe : faire une jointure.

Qu'est-ce que cela veut dire ?

1.1 Mécanisme de la jointure (interne)

Principe du JOIN, INNER JOIN

On veut créer une "nouvelle" table qui possède tous les attributs de la table 1 et tous les attributs de la table 2.

Pour cela, on part d'une première table (disons la table 1 qui possède une clé étrangère) : pour chacun des n-uplets 1, on va cherche (dans l'autre table) le n-uplet 2 pour lequel la valeur de la clé primaire correspond à la valeur de la clé étrangère. On crée alors un nouvel n-uplet à partir du n-uplet 1 en rajoutant les valeurs du n-uplet 2 pour les attributs manquants.

On obtient alors un nouveau n-uplet, plus complet. Comme si nous n'avions qu'un seul tableau.

Notez bien qu'ici, nous ne formons aucun n-uplet incomplet dans notre réponse : les entrées pour lesquelles la clé étrangère est non renseignée n'apparaissent pas dans la réponse.

Avec une telle jointure, le jeu Donkey Kong n'apparaîtra plus. C'est comme ça.

On rajoute les infos sur la console en plus des infos sur le jeu lui-même

C'est ce qu'on nomme une jointure interne (INNER JOIN). C'est la jointure la plus commune.

Exemple de fonctionnement avec Python

Les n-uplets nommés sont implémentés par des dictionnaires (on prendrait des tuples pour de simples n-uplets).

Chaque table est donc une list-python de dictionnaires : list[dict].

Voici comment on peut réaliser la jointure :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
# Déclaration des fonctions def jonction(table:list[dict], nom_pk:str, valeur_cherchee:int) -> dict: '''Renvoie le n-uplet de la table qui a cette valeur de clé primaire VALIDE''' for nuplet in table: # Pour chaque dictionnaire dans la table if nuplet[nom_pk] == valeur_cherchee: # Si ce n-uplet a la bonne valeur de clé primaire return nuplet # Renvoie le n-uplet (et sort donc définitement) def jointure(table1:list[dict], fk:str, table2:list[dict], pk:str) -> list[dict]: """Jointure des tables table1 avec clé étrangère fk et table2 avec clé primaire pk""" # PROTOTYPE BASIQUE : aucun attribut ne doit porter le même nom ! reponse = [] # Tableau dynamique de réponse for nuplet1 in table1: # pour chaque n-uplet de la table 1 if nuplet1[fk] != None: # si il possède une clé étrangère valide nuplet2 = jonction(table2, pk, nuplet1[fk]) # nuplet2 a une clé primaire qui correspond nuplet_obtenu = {} # nouveau n-uplet qu'on va former for cle, valeur in nuplet1.items(): # pour chaque cle et valeur du premier n-uplet nuplet_obtenu[cle] = valeur # on crée une même clé-valeur dans le nouveau for cle, valeur in nuplet2.items(): # pour chaque cle et valeur du second n-uplet nuplet_obtenu[cle] = valeur # on crée une même clé-valeur dans le nouveau reponse.append(nuplet_obtenu) # on rajoute le nouveau n-uplet dans le t.dyna. else: pass # on ne fait donc rien si la clé étrangère ne pointe vers rien return reponse # PROGRAMME DE TEST if __name__ == '__main__': jeu = [ {'j_id':7, 'j_jeu':'Flight Simulator', 'j_description':"Simulation d'avion", 'j_sortie':1980, 'j_éditeur':'subLOGIC', 'j_genre':'Simulateur', 'j_id_support':1}, {'j_id':8, 'j_jeu':'DONKEY KONG', 'j_description':"Un méchant singe géant", 'j_sortie':1981, 'j_éditeur':'Nintendo', 'j_genre':'Plate-formes', 'j_id_support':None}, {'j_id':9, 'j_jeu':'PIFALL!', 'j_description':"Pitfall Harry, un explorateur", 'j_sortie':1982, 'j_éditeur':'Activision', 'j_genre':'Plate-formes', 'j_id_support':2}, {'j_id':10, 'j_jeu':'PIFALL!', 'j_description':"Pitfall Harry, un explorateur", 'j_sortie':1983, 'j_éditeur':'Nintendo', 'j_genre':'Plate-formes', 'j_id_support':3}, {'j_id':11, 'j_jeu':'Boulder Dash', 'j_description':"Rockford, mineur téméraire", 'j_sortie':1983, 'j_éditeur':'First Star Software', 'j_genre':'Plate-formes', 'j_id_support':3} ] console = [ {'c_id':1, 'c_nom':'Apple II', 'c_RAM':'4 ko', 'c_date_sortie':'1977-06-10'}, {'c_id':2, 'c_nom':'Atari 2600', 'c_RAM':'4 ko', 'c_date_sortie':'1977-10-14'}, {'c_id':3, 'c_nom':'C64', 'RAM':'c_64 ko', 'c_date_sortie':'1982-08-01'} ] nouvelle_table = jointure(jeu, 'j_id_support', console, 'c_id') for nuplet in nouvelle_table: # pour chaque n-uplet de la jointure print(nuplet) # affiche ce n-uplet

Voici l'affichage obtenu dans la console après jointure : on obtient bien des dictionnaires qui ont les clés des deux tables jeu et console réunies et avec une jointure correctement réalisée.

{'j_id': 7, 'j_jeu': 'Flight Simulator', 'j_description': "Simulation d'avion", 'j_sortie': 1980, 'j_éditeur': 'subLOGIC', 'j_genre': 'Simulateur', 'j_id_support': 1, 'c_id': 1, 'c_nom': 'Apple II', 'c_RAM': '4 ko', 'c_date_sortie': '1977-06-10'} {'j_id': 9, 'j_jeu': 'PIFALL!', 'j_description': 'Pitfall Harry, un explorateur', 'j_sortie': 1982, 'j_éditeur': 'Activision', 'j_genre': 'Plate-formes', 'j_id_support': 2, 'c_id': 2, 'c_nom': 'Atari 2600', 'c_RAM': '4 ko', 'c_date_sortie': '1977-10-14'} {'j_id': 10, 'j_jeu': 'PIFALL!', 'j_description': 'Pitfall Harry, un explorateur', 'j_sortie': 1983, 'j_éditeur': 'Nintendo', 'j_genre': 'Plate-formes', 'j_id_support': 3, 'c_id': 3, 'c_nom': 'C64', 'RAM': 'c_64 ko', 'c_date_sortie': '1982-08-01'} {'j_id': 11, 'j_jeu': 'Boulder Dash', 'j_description': 'Rockford, mineur téméraire', 'j_sortie': 1983, 'j_éditeur': 'First Star Software', 'j_genre': 'Plate-formes', 'j_id_support': 3, 'c_id': 3, 'c_nom': 'C64', 'RAM': 'c_64 ko', 'c_date_sortie': '1982-08-01'}

D'autres types de jointure existent, nous n'en parlerons pas ici.

1.2 Lever l'ambigüité des noms d'attributs

Problématique

Lorsqu'il n'y a qu'une seule table, pas de risque de confondre si un attribut se nomme id par exemple.

Lorsqu'il a deux tables, jeu qui contient j_id et console qui contient c_id, cela reste encore compréhensible.

Par contre, avec deux tables, jeu qui contient id et console qui contient id, cela devient problématique pour savoir de quel id on parle...

Solution à appliquer dès qu'il a une jointure

Pour différencier sans ambigüité les attributs des relations, on applique le même principe que pour les attributs des objets : on note le nom de la relation suivi d'un point et du nom de l'attribut.

Ainsi, en SQL, avec deux tables, jeu qui contient id et console qui contient id, on notera :

  • jeu.id
  • console.id
CONCLUSION

Dès qu'une jointure pointe son nez, on utilisera la notation du point dans la requête (table.attribut) ce qui permettra de lever toute ambiguïté.

Regardons comment gérer cela en SQL. Commençons par voir la situation mentalement sous cette forme : on garde la table jeu et on voudrait lui ajouter les attributs de la table console.

id jeu description sortie editeur genre fichier_image id_support id nom RAM date_sortie
1 Flight Simulator Simulation de piotage d'avion avec des pixels gros comme des camions ! 1980 subLOGIC Simulateur Flight Simulator 1
2 DONKEY KONG Un méchant singe géant a capturé la fiancé de JumpMan (qui portera plus tard le nom de Mario). Guide JumpMan pour qu'il délivre sa dulcinée. 1981 Nintendo Plate-formes Donkey Kong NULL
3 PITFALL! Pitfall Harry, un explorateur, ramasse des objets éparpillés dans la jungle. 1982 Activision Plate-formes Donkey Kong 2
4 PITFALL! Pitfall Harry, un explorateur, ramasse des objets éparpillés dans la jungle. 1983 Activision Plate-formes Donkey Kong 3
5 Boulder Dash Rockford, mineur téméraire, ramasse des diamants et tente de ne pas se faire écraser par les énormes pierres instables. 1983 First Star Software Plate-formes Boulder Dash 3

Il reste maintenant à remplir les derniers champs de la table résultante. On ne va pas les remplir au hasard : nous allons réaliser la liaison entre les tuples des deux tables en explicitant quelle clé étrangère référence quelle clé primaire.

1.3 Clause JOIN table ON cle_primaire = cle_etrangere

Principe

Le principe global est d'écrire quelque chose qui ressemble à

CONCATENER les valeurs d'un n-uplet de A et d'un n-uplet de B LORSQUE la valeur d'une clé étrangère d'un n-uplet de A vaut la valeur d'une clé primaire d'un n-uplet de B.

Pour formuler cela en SQL, il faut utiliser deux nouveaux mots-clés :

  1. JOIN table qui précise dans quelle table aller chercher les nouveaux attributs, puis
  2. ON cle_primaire = cle_etrangere ou ON cle_etrangere = cle_primaire qui précise avec quels attributs réaliser la jointure.
Exemple avec les relations jeu et console
  • jeu qui possède une clé étrangère id_support vers console
  • console dont la clé primaire est id.
1 2 3
SELECT * FROM jeu JOIN console ON jeu.id_support = console.id

Cela fonctionne également sous cette forme :

1 2 3
SELECT * FROM jeu JOIN console ON console.id = jeu.id_support

Ou encore 

1 2 3
SELECT * FROM console JOIN jeu ON jeu.id_support = console.id

On obtient alors ceci :

id jeu description sortie editeur genre fichier_image id_support id nom RAM date_sortie
1 Flight Simulator Simulation de piotage d'avion avec des pixels gros comme des camions ! 1980 subLOGIC Simulateur Flight Simulator 1 1 Apple II 4 ko 1977-06-10
3 PITFALL! Pitfall Harry, un explorateur, ramasse des objets éparpillés dans la jungle. 1982 Activision Plate-formes Donkey Kong 2 2 Atari 2600 4 ko 1977-10-14
4 PITFALL! Pitfall Harry, un explorateur, ramasse des objets éparpillés dans la jungle. 1983 Activision Plate-formes Donkey Kong 3 3 C64 64 ko 1982-08-01
5 Boulder Dash Rockford, mineur téméraire, ramasse des diamants et tente de ne pas se faire écraser par les énormes pierres instables. 1983 First Star Software Plate-formes Boulder Dash 3 3 C64 64 ko 1982-08-01

On remarquera un point essentiel : le n-uplet de Donkey Kong n'est plus là puisque sa clé étrangère (valant NULL, absence d'information) ne peut pas correspondre à une autre clé primaire.

Si vous ne voulez pas tout récupérer, il suffit de projeter uniquement les attributs voulus avec SELECT :

1 2 3
SELECT jeu.jeu, console.name FROM jeu JOIN console ON jeu.id_support = console.id

03° Même si c'est possible, pourquoi ne faut-il pas utiliser le même nom pour la relation et l'un de ses attributs ?

...CORRECTION...

Tout simplement car c'est source de confusion.

En python, on n'utilise pas non plus une variable locale portant le même nom que sa fonction par exemple.

2 - Jointure entre les tables emploi-titre

Voici le schéma relationnel (sous forme de graphique cette fois) des trois relations emploi , titre et personne de la base de données que nous allons encore utiliser aujourd'hui.

Version graphique :

Les liaisons entre les 3 relations

Je rappelle encore que je n'ai pas choisi les noms des clés primaires sur les tables personne et titre. Par contre, sur emploi, j'ai bien utilisé id et l'ai forcé à être géré automatiquement par le SGBD.

Version en SQL

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
CREATE TABLE personne ( id INTEGER UNIQUE, nconst VARCHAR(12), name VARCHAR(50), birth_year INTEGER CHECK(birth_year IS NULL OR (birth_year > 1000 AND birth_year < 3000)), death_year INTEGER CHECK(death_year IS NULL OR (death_year > 1000 AND death_year < 3000)), primary_profession TEXT, known_for_titles TEXT, PRIMARY KEY(nconst) ); CREATE TABLE titre ( id INTEGER UNIQUE, tconst VARCHAR(9), title_type VARCHAR(15), primary_title VARCHAR(40), original_title VARCHAR(40), start_year INTEGER, end_year INTEGER, runtime_minutes INTEGER, genres TEXT, PRIMARY KEY(tconst) ); CREATE TABLE emploi ( id INTEGER, tconst VARCHAR(9), ordering INTEGER, nconst VARCHAR(12), category VARCHAR(40), job VARCHAR(40), characters VARCHAR(100), PRIMARY KEY(id), FOREIGN KEY (tconst) REFERENCES titre(tconst), FOREIGN KEY (nconst) REFERENCES personne(nconst) );

04° Fournir le schéma relationnel de la relation titre en les écrivant sous forme abstraite. On utilisera donc les notations soulignements et #.

...CORRECTION...

1 2 3 4 5 6 7 8 9 10 11
titre ( id INTEGER, tconst VARCHAR(9), title_type VARCHAR(15), primary_title VARCHAR(40), original_title VARCHAR(40), start_year INTEGER, end_year INTEGER, runtime_minutes INTEGER, genres TEXT )

05° Fournir le schéma relationnel de la relation emploi en les écrivant sous forme abstraite. On utilisera donc les notations soulignements et #.

Comment doit-on utiliser JOIN table ON cle_primaire = cle_etrangere si on veut réaliser la jointure entre les tables titre et emploi ?

...CORRECTION...

1 2 3 4 5 6 7 8 9
emploi ( id INTEGER, #tconst VARCHAR(9), ordering INTEGER, #nconst VARCHAR(12), category VARCHAR(40), job VARCHAR(40), characters VARCHAR(100), ) CLE ETRANGERE tconst en liaison avec titre(tconst) CLE ETRANGERE nconst en liaison avec personne(nconst)
FROM emploi JOIN titre ON titre.tconst = emploi.tconst

Ou encore

FROM titre JOIN emploi ON titre.tconst = emploi.tconst

06° Ouvrir la base de données avec DBBrownser si ce n'est pas encore fait. Proposer la requête qui permet de projeter ceci pour chaque emploi dans emploi :

  1. la clé primaire de cet emploi,
  2. la catégorie de l'emploi,
  3. le vrai nom du titre (primary_title, pas juste la valeur de la clé étrangère) et
  4. l'identifiant nconst de l'employé (pas son vrai nom).

Identifier la clé primaire et la clé étrangère.

...CORRECTION...

On réalise la jointure en comparant la clé étrangère emploi.tconst à la clé primaire titre.tconst.

1 2 3
SELECT emploi.id, emploi.category, titre.primary_title, emploi.nconst FROM emploi JOIN titre ON titre.tconst = emploi.tconst
x

07° Quelle requête doit-on faire pour obtenir la même chose mais uniquement avec les films de 2016 et plus ? Trier le résultat par année de sortie. On rajoutera l'année dans la réponse de façon à vérifier si la requête fonctionne bien.

...CORRECTION...

1 2 3 4 5
SELECT emploi.id, emploi.category, titre.primary_title, emploi.nconst, titre.start_year FROM emploi JOIN titre ON titre.tconst = emploi.tconst WHERE titre.start_year > 2015 ORDER BY titre.start_year DESC
x

3 - Liaison emploi-personne

Nous allons maintenant faire le lien entre la relation emploi et la relation personne.

Les liaisons entre les 3 relations

08° Quelle requête doit-on faire pour obtenir le tconst du titre, le nom de la personne occupant un emploi dans ce film, et le poste qu'elle occupe ?

...CORRECTION...

1 2 3
SELECT emploi.tconst, personne.name, emploi.category FROM emploi JOIN personne ON emploi.nconst = personne.nconst

4 - Double jonction

On remarquera que la relation emploi est particulière puisqu'elle contient deux clés étrangères. Elle joue un rôle central dans les jonctions entre les titres et les personnes qui y ont participé : titre - emploi - personne. Nous avions la même chose avec la relation emprunt lorsque nous avons travaillé sur les BDD de la bibliothèque.

Les liaisons entre les 3 relations

En réalité, on peut utiliser plusieurs JOIN ...ON ... = ... dans une requête. Nous allons donc pouvoir faire la liaison entre un titre et les gens qui ont travaillé sur ce projet.

09° Expliquer clairement ce que fait cette requête.

1 2 3 4
SELECT titre.primary_title, personne.name, emploi.category FROM emploi JOIN personne ON emploi.nconst = personne.nconst JOIN titre ON emploi.tconst = titre.tconst

...CORRECTION...

On va créer des nuplets en utilisant les trois tables à la fois.

L2 : On commence par récupérer les attributs de la table emploi.

L3 : On rajoute ensuite les attributs de la relation personne (en cherchant une liaison de type valeur de clé étrangère = valeur de clé primaire).

L4 : On rajoute finalement les attributs de la relation titre (en cherchant une liaison de type valeur de clé étrangère = valeur de clé primaire).

L1 : On projette uniquement les attributs demandés sur la première ligne.

10° Filtrer les résultats précédents pour obtenir uniquement les films des années 2000 précisement.

Pensez à réaliser au préalable une requête SELECT DISTINCT pour obtenir les catégories disponibles de façon à voir comment se nomme la catégorie "film" dans cette table.

...CORRECTION...

1 2 3 4 5
SELECT titre.primary_title, personne.name, emploi.category FROM emploi JOIN personne ON emploi.nconst = personne.nconst JOIN titre ON emploi.tconst = titre.tconst WHERE titre.start_year = 2000 AND titre.title_type = 'movie
AS

Le nom des relations sont parfois assez longues à taper. On peut utiliser des alias de façon à simplifier les notations.

1 2 3 4 5
SELECT t.primary_title, p.name, e.category FROM emploi as e JOIN personne AS p ON e.nconst = p.nconst JOIN titre AS t ON e.tconst = t.tconst WHERE t.title_type = "tvSeries"

En réalité, cela ne sert pas qu'à cela car changer de nom permet de gérer plus facilement les collusions entre les requêtes imbriquées. Mais tout cela est hors programme.

5 - Autres exercices

11° Comptabiliser le nombre d'emplois où on dispose à la fois d'informations sur le film et les personnes qui y ont participé.

Il suffit donc de faire la jointure entre les trois tables et d'utiliser SELECT pour récupérer uniquement la clé primaire de emploi.

Une fois que cela marche, il suffit d'utiliser un COUNT sur les n-uplets récupérés.

...CORRECTION...

1 2 3 4 5
SELECT COUNT(*) FROM emploi JOIN personne ON emploi.nconst = personne.nconst JOIN titre ON emploi.tconst = titre.tconst WHERE titre.title_type = "movie"

12° Comptabiliser le nombre de films de plus de 180 minutes pour lesquels on dispose d'employés : il suffit de chercher les valeurs DISTINCTES de l'un des attributs de cette jointure titre-emploi et de les compter.

...CORRECTION...

1 2 3 4 5
SELECT COUNT(DISTINCT titre.primary_title) FROM emploi JOIN personne ON emploi.nconst = personne.nconst JOIN titre ON emploi.tconst = titre.tconst WHERE titre.title_type = "movie" AND runtime_minutes > 180

13° Obtenir la liste des titres dans lesquels Bruce Willis a participé d'une façon où d'une autre. Vous pourriez utiliser une recherche de ce type :

5
WHERE personne.name LIKE '%Bruce Willis%'

...CORRECTION...

1 2 3 4 5
SELECT DISTINCT titre.primary_title, titre.start_year FROM emploi JOIN personne ON emploi.nconst = personne.nconst JOIN titre ON emploi.tconst = titre.tconst WHERE personne.name LIKE '%Bruce Willis%'

Pourquoi DISTINCT ? Simplement pour ne pas comptabiliser deux fois un film où il aurait été acteur et producteur par exemple.

14° Obtenir la liste des titres dans lesquels Bruce Willis a participé en tant qu'acteur. On affichera également les rôles qu'il incarne dans ces films.

...CORRECTION...

1 2 3 4 5
SELECT titre.primary_title, titre.start_year, emploi.characters FROM emploi JOIN personne ON emploi.nconst = personne.nconst JOIN titre ON emploi.tconst = titre.tconst WHERE p.name LIKE '%Bruce Willis%' AND emploi.category = 'actor'

6 - FAQ

NULL et None, c'est pareil ?

NULL

NULL signifie "Absence d'informations".

Les bases de données sont conçues pour répondre FAUX à ceci : NULL = NULL.

En effet, les bases de données doivent répondre exactement. Or, on ne peut pas affirmer qu'une absence d'informations corresponde à une autre absence d'informations. Puisque le champ n'est pas rempli, il est possible que les deux soient en réalité égaux ou différents. La réponse est donc FAUX.

1 2 3
SELECT * FROM titre WHERE NULL = NULL

Vous n'allez rien obtenir avec cette requête : NULL = NULL sera toujours évalué à FAUX.

Comment tester alors qu'une valeur est NULL ? Il faut utiliser cette façon :

1 2 3
SELECT * FROM titre WHERE NULL is NULL

Cette fois, la condition de WHERE sera toujours vraie : on aura donc toute la table.

En Python, on aurait Vrai dans les deux cas avec None :

>>> None == None True >>> None is None True

J'espère vous avoir montrer que None et Null ne caractérise pas le même type d'informations.

On retiendra simplement la structure de base à base de

1 2 3 4 5
SELECT * FROM table_a JOIN table_b ON table_a.cle_etrangere = table_b.cle_primaire WHERE condition(s) ORDER BY expression
  1. SELECT : on choisit les attributs qu'on veut réellement récupérer dans les nuplets obtenus par FROM WHERE. On peut également faire des calculs (agrégation) sur ces nuplets avec MIN, MAX, AVG, SUM ou COUNT. L'utilisation de l'étoile * veut dire de récupérer l'intégralité des attributs disponibles sur les nuplets obtenus.
  2. FROM : on indique la table dans laquelle on veut récupèrer des nuplets
  3. JOIN ON : on indique la table qu'on veut fusionner avec la précédente et on précise quelle clé primaire comparer à quelle clé étrangère
  4. WHERE : on fournit les conditions à respecter pour qu'un nuplet soit sélectionné. On pourra utiliser AND, OR, LIKE...
  5. ORDER BY : on fournit l'attribut de tri avec un suffixe ASC ou DESC

Activité publiée le 20 01 2021
Dernière modification : 24 01 2021
Auteur : ows. h.