Bonsoir py86acces,
Parlons du mariage...
Je traduis ce qu’a écrit Hugh Darwen en 1987, et qui fut repris en tant que contribution darwenienne (signée du pseudonyme anagrammique Andrew Warden) dans l’ouvrage de Chris Date Relational Database, Writings 1985-1989, paru en 1990 :
« Étudions maintenant l’opérateur Jointure naturelle et voyons comment il nous change la vie. Je le représente selon la syntaxe suivante :
MARRIAGE (table-expression-1, table-expression-2)
On peut voir ainsi la merveilleuse union accomplie par cet opérateur :
Dans un premier temps, il y a les tendres préliminaires à l’occasion desquels les colonnes des deux opérandes sont examinées, afin de voir lesquelles portent le même nom. Celles-ci sont appelées « colonnes communes » quand, outre le même nom, elles sont du même domaine.
Dans un deuxième temps a lieu l’accouplement : à cette occasion les lignes compatibles des deux opérandes sont jointes (à savoir les lignes qui ont la même valeur pour les colonnes communes).
Il y a enfin, l’orgasme grandiose quand un ensemble de colonnes communes est éjaculé.
Le fruit de cette union est un individu aussi parfait qu’on peut le souhaiter, ayant hérité des caractéristiques de ses parents. »
Autrement dit, de même que l’union de deux ensembles E1 et E2 produit un ensemble E3, suite au mariage de deux tables T1 et T2 naît une table T3 (et pas une chaise !), de même nature que ses parents, donc pouvant à son tour se marier et plus généralement participer à toute opération de l’algèbre relationnelle : on est dans un monde relationnellement clos. Attention quand même avec SQL, coupable d’autoriser la production de sacs (bags), incompatibles avec l’algèbre relationnelle (lignes en double, colonnes sans nom ou en double, présence de Null...)
Reprenons la requête :
SELECT matos.idmat, max(prixmatos.datemaj) AS datemax
FROM matos INNER JOIN prixmatos ON matos.idmat = prixmatos.idmat
GROUP BY matos.idmat ;
Le résultat est une table, appelons-la T, comportant deux colonnes, idmat et datemax. Elle contient une ligne par idmat ayant répondu présent lors de la jointure :
T idmat datemax
----- ----------
1 01/07/2015
2 01/07/2015
4 01/07/2015
Le produit pour lequel idmat = 3 ne figure pas parce qu’absent de la table prixmatos. Par ailleurs, puisqu’on a utilisé la fonction MAX, pour idmat = 1, SQL a retenu la date du 01/07/2015, alors que si on avait utilisé la fonction MIN, c’est la date du 20/06/2015 qui aurait été retenue.
Il s’agit maintenant de compléter ce résultat, afin de faire figurer le prix du produit. En présupposant l’existence de la table T, il suffirait d’exécuter la requête :
SELECT prixmatos.idmat, prixmatos.datemaj, prixmatos.prix
FROM prixmatos INNER JOIN T ON prixmatos.idmat = T.idmat AND prixmatos.datemaj = T.datemax ;
Mais hélas ! la table T est purement virtuelle...
Heureusement, en 1987 (dans l’ouvrage que j’ai mentionné tout au début), Andrew Warden lança le défi suivant (et dont l’origine remonte au langage ISBL, vieux de 40 ans, selon lequel toute expression relationnelle peut être opérande d’un opération relationnelle) :
« Can a table expression be used anywhere a table name is used? »
La réponse est évidemment positive, puisque :
« A table name is merely the trivial case of table expression! »
La norme SQL a suivi Darwen (qui y fut un des représentants pour le compte du Royaume-Uni) et depuis la sortie de la version SQL-1992 de cette norme, on peut effectuer des jointures auxquelles participent non plus seulement des noms de tables, mais des expressions. Les SGBD s’y sont mis, petit à petit.
Pour reprendre la requête :
SELECT prixmatos.idmat, prixmatos.datemaj, prixmatos.prix
FROM prixmatos INNER JOIN T ON prixmatos.idmat = T.idmat AND prixmatos.datemaj = T.datemax ;
On peut donc y remplacer la table T par l’expression qu’elle représente :
SELECT prixmatos.idmat, prixmatos.datemaj, prixmatos.prix
FROM prixmatos
INNER JOIN
(
SELECT matos.idmat, max(prixmatos.datemaj) AS datemax
FROM matos INNER JOIN prixmatos ON matos.idmat = prixmatos.idmat
GROUP BY matos.idmat
) AS T
ON prixmatos.idmat = T.idmat AND prixmatos.datemaj = T.datemax ;
Est-ce plus clair ? Cela reste-t-il brumeux ?
Partager