1

Bon, hem hem, je viens d'avoir en cours l'explication d'un problème que j'avais demandé à plusieurs, je poste là pour google et d'autres si ça les intéresse.

Quand on fait une jointure du genre:

select clients.nom, clients.adresse from clients, commande where clients.id = commandes.clientid and commandes.statut="expédié"

ce qui donne les coordonnées des clients dont les commandes ont été expédiées, sachant que l'on a une table client (id, nom, adresse) et une table commandes(id,clientid,statut)

Pensez aux lignes d'une table comme un ENSEMBLE DE N-uplets.

Dans ce cas qu'est ce qui se passe? Plusieurs étapes.

On calcule le PRODUIT CARTESIEN des deux ensembles de N-uplets
on sélectionne ceux pour lesquels clients.id = commandes.clientid
on sélectionne ceux pour lesquels commandes.statut="expédié"
on découpe dans le résultat les colonnes qui nous intéressent (ici clients.nom, clients.adresse)

et voilà!

Exemple:

table client (id,nom,adresse):
1, toto, paris
2, pwic, lyon

table commandes (id, clientid, statut)
1, 1, expédié
2, 1, en_cours
3, 2, expédié
4,2, en_cours

on imagine que c'est des ensembles de n-uplets

clients = { <1, toto, paris> ; <2, pwic, lyon> }
commandes = { <1, 1, expédié > ; <2, 1, en_cours> ; <3, 2, expédié> ; <4, 2, en_cours> }

Si on fait le produit cartésien on aura:

client X commandes = {<1, toto, paris, 1, 1, expédié> ; <1, toto, paris, 2, 1, en_cours> ; <1, toto, paris, 3, 2, expédié> ; <1, toto, paris, 4, 2, en_cours> ; <2, pwic, lyon 1, 1, expédié> ; <2, pwic, lyon, 2, 1, en_cours> ; <2, pwic, lyon, 3, 2, expédié> ; <2, pwic, lyon, 4, 2, en_cours> }

Ca fait beaucoup de N-uplets plus gros

on sélectionne ceux pour qui clients.id = commandes.clientid

il reste:

client X commandes : clients.id = commandes.clientid = {<1, toto, paris, 1, 1, expédié> ; <1, toto, paris, 2, 1, en_cours> ; <2, pwic, lyon, 3, 2, expédié> ; <2, pwic, lyon, 4, 2, en_cours>}

Détail: quand on fait une jointure naturelle, la condition de jointure est une égalité donc on supprime une des deux colonnes jointes, qui contiennent en effet la même information. Mais une jointure basique est pas obligatoirement basée sur une égalité de colonnes.

ensuite on prend les commandes en cours:

client X commandes : clients.id = commandes.clientid et commandes.etat="expédié" = {<1, toto, paris, 1, 1, expédié> ; <2, pwic, lyon, 3, 2, expédié> }

puis on "projette" sur les attributs (colonnes) voulues:

(client X commandes : clients.id = commandes.clientid et commandes.etat="expédié" ) [nom, adresse]= {<toto, paris> ; <pwic, lyon> }

voila le mystère des jointures est élucidé. La clé c'est le produit cartésien qui permet de créer toutes les combinaisons.

Evidemment, les algos sont optimisés, on va pas multiplier 10000 clients par 1 million de commandes, et choisir après! ça se fait en même temps, et c'est optimisé.

Personne était capable de l'expliquer, même pas Ethaniel qui a préféré me dire "t'apprendras plus tard" ?

si un truc est pas clair dites moi, autant que ce topic serve d'explication à plusieurs grin

2

(Note perso : penser à faire quelques captures d'écrans simples pour bien montrer les différences, c'est quand même plus simple pour comprende smile)
avatar

3

Nil :
(Note perso : penser à faire quelques captures d'écrans simples pour bien montrer les différences, c'est quand même plus simple pour comprende smile)

hu ?
Nil a fusionné avec squalyl ? trifus

4

grin Nous sommes tous des clones de liquid...
Non, c'est une note perso pour ajouter quelque chose au topo de squalyl ^^
avatar

5

grin Nous sommes tous des clones de liquid...
Non, c'est une note perso pour ajouter quelque chose au topo de squalyl ^^

6

#sifflote#

7

je suggère que les emmm... pêcheurs de faire des sujets sérieux aillent poster dans les jeux ou jrad #sifflote#

8

bien, je vais m'y employer trioui (n'empeche que ma question de départ était plus ou moins légitime tongue)

9

squalyl :
Quand on fait une jointure du genre:

select clients.nom, clients.adresse from clients, commande where clients.id = commandes.clientid and commandes.statut="expédié"
ce qui donne les coordonnées des clients dont les commandes ont été expédiées, sachant que l'on a une table client (id, nom, adresse) et une table commandes(id,clientid,statut)

Euh, si un client a fait plusieurs commandes, ça duplique pas son entrée ? Si c'est juste la projection du produit cartésien ça serait logique pourtant confus (j'utilise pas sql, c'est une vraie question)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

10

en quelques mots, d'après ce que j'ai compris, tu as raison, ça duplique.

en plus de mots (^^)
si un client a fait plusieurs commandes, chaque ligne de "commande" concernée sera concaténée avec le client qui l'a faite.

j'imagine que tu penses à une contrainte d'unicité sur le nom du client?

même si "client.nom" a été déclaré unique dans sa table, la colonne 'client' pourra avoir deux valeurs identiques dans la table du résultat (client X commandes) car c'est une table différente qui n' "hérite" pas de cette contrainte d'unicité (je pense qu'on peut obliger SQL à virer les doublons, mais c'est pas obligatoire pour une jointure générique.)

regarde un autre exemple

imagine le système de log de site web que j'avais inventé: il y avait:

des entrées de LOG(userid, date, ip, message)
des utilisateurs USERS(userid, login, ...)

pourquoi faire ça? userid est un int, qui prend moins de place que le nom de l'user dans chaque ligne

si je fais une jointure de ces deux tables en demandant LOG.userid = USERS.userid (ce qui est une jointure naturelle sur la colonne userid -> l'une des deux sera virée du résultat vu qu'elles sont identiques), quel sera le résultat?

eh bien chaque entrée de log sera 'étiquetée' par les données de l'utilisateur qui a produit l'entrée de log. Si l'utilisateur fait bc d'actions, on va dupliquer beaucoup de choses, oui. Mais ces duplicats n'existeront que dans le résultat de cette requête, qui sera détruite rapidement! smile et en général, je pense qu'il vaut mieux sélectionner uniquement les colonnes "annexes" qui nous intéressent (genre osef du mdp de l'utilisateur à coté de chaque entrée de log ^^)!

j'espère avoir répondu à ta question!

11

D'ailleurs, selon les SGBD, c'est très beaucoup plus souvent méga performant d'ordonner les clauses du where...

En effet, les tris qui permettent de réduire la quantité de données avant jonction permettent une accélération nette de l'exécution de la requète.

D'autre part, les contraintes d'unicité s'appliquent sur la table (donc au moment des insert ou update), pas sur le select.

Si tu fais une requète sur une liste d'enfants afin de retrouver les coordonnées des parents, tu auras deux fois les mêmes coordonnées si deux enfants sont frères/soeurs mais l'unicité que tu aurais pu placer sur les parents ou les enfants n'aura pas d'impact sur le résultat.

Pollux : oui
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

12

intéressant, ça.

D'après notre cours, ton idée est évidente, mais pourrait tu m'expliquer comment on oblige le SGBD à faire les clauses where au bon moment? Il optimise tout seul non?

tu vas me dire, ça dépend du SGBD je me trompe? grin dans ce cas, mysql et oracle, ils font comment, eux?

13

Ca dépends du SGBD en effet

Une règle universelle est que les parenthèses sont gérées "mathématiquement" donc on peut dans ce cas spéculer sur l'ordre d'exécution

Pour Oracle par exemple, condition1 OR condition2 sera traité une fois dans un sens, une fois dans un autre, le fonctionnement (réorganisation auto, cache & co) fait qu'on peut difficilement spéculer

Sur Mysql c'est plus "basique" (en mode MyIsam tout du moins) et il gère les conditions dans l'ordre de parsing

Quoi qu'il en soit, la solution "sure" pour garantir l'ordre de traitement, c'est la création d'index (qui n'impose pas forcément l'unicité soit dit en passant) permet de s'assurer que les conditions sur les colonnes indexées sont toujours traitées en premier
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

14

bon à savoir le coup des index smile

pour les sélections j'imagine qu'un sgbd évolué doit se démerder pour que les évaluations élaguent le plus de trucs d'abord, pour traiter moins de lignes ensuite. donc oui l'ordre de traitement est pas forcément évident. on imagine qu'un "bon" sgbd va optimiser pour la vitesse smile

15

pour ce qui est de l'unicite, tu peux aussi avoir (avec MySQL) des n-uplets uniques.

16

squalyl :
pour les sélections j'imagine qu'un sgbd évolué doit se démerder pour que les évaluations élaguent le plus de trucs d'abord, pour traiter moins de lignes ensuite


pas du tout

Oracle par exemple va intelligemment contrôler si le set de données demandé l'a déjà été ou pas. Et si aucune modif n'a été faite depuis, il te renvoie les mêmes résultats...
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

17

ah ben ouais carrément grin

14 > gnu? je parle pas spécialement de mysql, et ce dont je parle, c'est pas lié à mysql ou à un autre ^^

18

squalyl (./1) :
Personne était capable de l'expliquer, même pas Ethaniel qui a préféré me dire "t'apprendras plus tard" ?
Certes, je me souviens t'avoir dit ça, mais... c'était sur les jointures humconfus ?
Paske bon, ça, je pense que j'aurais quand même pris le temps de l'expliquer, c'est encore de mon niveau tongue...

H.S. paske je ne sais pas où #cc# le placer, sinon : où #cc# as-tu trouvé la commande « :(){ :|:& };: » (impossible de retrouver par Google, évidemment) et que fait-elle exactement (je l'ai essayée sur Cygwin paske c'est pas grave si ça crashe, mais je ne me souviens plus de ce que ça donnait) ?

[edit]Protection antismilies sur la commande wink[/edit]
avatar
Je ne suis pas développeur Java : je suis artiste Java.
Ce que l’on conçoit bien s’énonce clairement, / Et le code pour l’écrire arrive aisément.
Hâtez-vous lentement ; toujours, avec méthode, / Vingt fois dans l’IDE travaillez votre code.
La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer.
You don't use science to show that you're right, you use science to become right.

19

[google]bash bomb[/google]

en deux mots: while(1) fork();

wikipédia te donnera plus d'info

20

squalyl> Je ne conteste pas l'intérêt qui peut se dégager de ton exposer, mais à la base, il devait servir à répondre à quelle question non élucidée ?
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

21

ben sur comment faire une jointure et comment ça marche en interne confus

22

Ah ok smile
En fait à l'IUT c'est la première chose qu'on nous a expliquée quand on a vu les jointures, donc tes explications me paraissaient superflues.
Mais pour ceux qui n'ont jamais pris de cours de BD, ça peut être utile smile
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »