Version complète: sur le forum Webmaster Hub : Souhaite jointure complete...
Webmaster Hub > Création et exploitation de Sites Internet > Les langages du Net > SQL
Bourinho
Salut,

Mon problème est le suivant : J'ai deux tables SQL table1 et table2.

La table1 contient tous les codes INSEE des villes que je souhaite enregistrer ainsi que les noms de ces memes villes.

La table2 contient une correspondance entre le code INSEE et le code postal mais cette correspondance est incomplete...

Si je fais une jointure entre ces deux tables, je perds des données de la table1...

Alors, ce que je voudrais pouvoir faire, c'est insérer les codes postaux dans ma table1 à partir de la table2... sans perdre les données de la table1 (si la correspondance n'est pas disponible dans la table2, je mets le code postal à NULL)

Si je fais un jointure, ça ne fonctionne pas (je perds les données de la table1)

Avec un UPDATE, faudrait que je fasse une boucle sur la table1 (36684 entrées...)...enfin, je dis "faudrait", mais c'est ce que mes connaissances de MySQL me disent whistling.gif

Enfin bref, j'y arrive pas! wacko.gif

Si je n'ai pas été assez clair, n'hésitez pas à me le faire savoir!

Par avance, merci!

PS : Je crois avoir trouver une piste avec la jointure externe!!!
michmuch51
Pour ma part je t'avoue que quand je veux manipuler des tables entières, je me fais un petit script en php qui ecrit exactement la commande mysql que je souhaite en faisant une boucle, c'est assez rapide et ca te permet de ballader tes données où tu veux dans le sens que tu veux.
Vincent
c'est possible de rendre une jointure externe facultative.

plus d'informations sur cette page LE SQL de A à Z : 3e partie - les jointures

regarde l'exemple 13, c'est tout a fait ton cas.
il faut utiliser LEFT OUTER JOIN ou RIGHT OUTER JOIN.
Bourinho
Bonjour à tous,

Merci pour vos reponses...

Mais il y a un truc qui me chagrine... une requete avec LEFT OUTER JOIN met beaucoup plus de temps qu'une requete avec une jointure naturelle!!! Alors qu'il n'y a pas tant de différences que ça...enfin dans mon cas...

Avec une jointure naturelle, la requete nécessite quelques secondes en étant large...

Avec la jointure externe, elle met plus d'une heure! Alors que cette jointure ne me donne que 11 entrées supplémentaires par rapport à la jointure naturelle!!! (sur plus de 36.000)

Vous avez une idée d'ou cela peut venir?

A+
Jeromnimo
Essaie avec un INNER JOIN, dans ton cas normalement ca devrait fonctionner...
(par contre mets bien ta table complete a gauche et l'autre à droite)

A priori tu n'as pas besoin de LEFT OUTER JOIN dans ton cas...
Vincent
CITATION(Jeromnimo @ lundi 17 juillet 2006, 14h52) *
Essaie avec un INNER JOIN, dans ton cas normalement ca devrait fonctionner...
(par contre mets bien ta table complete a gauche et l'autre à droite)

A priori tu n'as pas besoin de LEFT OUTER JOIN dans ton cas...


Je suis pas d'accord, s'il utilise INNER JOIN, les enregistrements dont le code postal sera à NULL vont sauter...
Maintenant, la table complete a gauche oui, avec LEFT OUTER JOIN (sinon a droite avec RIGHT OUTER JOIN)

Après Bourinho, si tu as 11 enregistrements problèmatique sur + de 36 000, est-ce que çà ne vaut pas le coup de faire une recherche pour completer la base de donnée au lieu de se compliquer la vie avec des jointures externes?
MarvinLeRouge
CITATION(Vincent @ lundi 17 juillet 2006, 18h18) *
Je suis pas d'accord, s'il utilise INNER JOIN, les enregistrements dont le code postal sera à NULL vont sauter...
Maintenant, la table complete a gauche oui, avec LEFT OUTER JOIN (sinon a droite avec RIGHT OUTER JOIN)


+1 pour les enregistrements qui vont sauter

CITATION(Vincent @ lundi 17 juillet 2006, 18h18) *
Après Bourinho, si tu as 11 enregistrements problèmatique sur + de 36 000, est-ce que çà ne vaut pas le coup de faire une recherche pour completer la base de donnée au lieu de se compliquer la vie avec des jointures externes?


Ou de faire un inner join, puis de récupérer les autres dans une 2ème requète avec un where, ou un autre truc du genre : un chouilla plus compliqué, mais potentiellement plus rentable.
Bourinho
Salut à tous,

CITATION(MarvinLeRouge @ lundi 17 juillet 2006, 19h22) *
+1 pour les enregistrements qui vont sauter
Ou de faire un inner join, puis de récupérer les autres dans une 2ème requète avec un where, ou un autre truc du genre : un chouilla plus compliqué, mais potentiellement plus rentable.


J'ai essayé de faire ça en deux requêtes... mais la seconde, je l'ai faite avec un "where" ou j'ai casé un "IS NOT EXIST" et ça rend le processus encore plus lent!

Et sinon, quant à faire cela à la main, je dois vous avouer que c'était la première fois que j'utilisais une jointure externe, donc je ne pouvais pas savoir que cela prendrait autant de temps wink.gif . Mais, la prochaine fois, je me poserai la question de savoir si j'ai un film à matter... Si c'est le cas, je laisse le PC chauffer pendant le OUTER JOIN, sinon je le fais à la main tongue.gif

Encore merci,

A+
Jeromnimo
Autant pour moi, la chaleur commence à me monter au cerveau, ça va pas bien des fois :-P

Par contre as-tu bien verifié tes index dans tes tables ? Il faut obligatoirement qu'ils soient indexés pour que la jointure soit rapide, sinon MySQL a du mal a gérer...

SI tu as PHPmyAdmin ou une console sql, essaye de faire un explain de ta requete avec le left outer join (ou right outer join) et dis nous ce que tu as dans les champs type.
Bourinho
Salut,

J'ai suivi ton conseil pour ce qui est du "EXPLAIN de ma requête". Je lui ai mis ça:
CODE
EXPLAIN SELECT villesfinales.CodeINSEE AS CodeINSEE,
villesfinales.Article AS Article,
villesfinales.nom AS Nom,
villesfinales.NomComplet AS NomComplet,
villesfinales.Departement AS Departement,
villesfinales.NumDepartement AS NumDepartement,
villesfinales.CodeRegion AS CodeRegion,
villesfinales.CodePostal AS CodePostal,
villestcd.Latitude AS Latitude,
villestcd.Longitude AS Longitude
FROM villesfinales LEFT OUTER JOIN villesTCD
ON (villesfinales.NomComplet=villestcd.Nom AND villesfinales.CodeRegion=villestcd.CodeRegion)


Résultat :
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE villesfinales ALL NULL NULL NULL NULL 36726
1 SIMPLE villesTCD ALL NULL NULL NULL NULL 68003

Ca ne ressemble pas à une optimisation de table!!! blush.gif

Ensuite, tu soulèves une piste qui me parait fort intéressant...celle des index!!! Ne sachant pas l'utilité de cela, j'en ai mis nulle part... blush.gif (A part une clé primaire sur les Codes INSEE...car ils sont censés être uniques!). Alors, je pense qu'en effet, mes tables sont loins d'être optimisées, mais je ne sais pas du tout quoi mettre en index ne sachant pas ce que cela change pour MySQL quand il tombe dessus!

Par avance, merci!

PS : J'ai lu que cela permettait de créer un arbre équilibré pour accélérer les recherches... Ca doit donc être bien utile dans mon cas en effet... wink.gif (Pour info, j'ai mis un index sur le Nom des villes mais pas sur CodeRegion (seulement 24 possibilités...). Je vous en dirai plus demain car je vais lancer cette requête demain pour la journée!

En fait, je viens de la lancer... et je comprends l'intérêt des index désormais!!!! ça a mis 6 secondes au lieu de plus de 3 heures!!! tongue.gif Merci à tous! (je crois que je vais m'intéresser de prêt à ces index!!!!)
Jeromnimo
Tant meiux si la piste a pu t'aiguiller comme il faut :-)
En ce qui concerne l'interpretation du EXPLAIN, il y le champ marqué ALL dans ton explain qui signifie que ce n'est pas optimisé du tout (il va falloir parcourir l'nesemble de la table a joindre pour chaque ligne de la première table (d'ou le temps prohibitif)
L'idéal est d'avoir ref lorsque tu fais une jointure.
Sinon, en ce qui concerne les champs à indexer, les clefs primaires le sont automatiquement si tu les a définies comme PRIMARY KEY, et il faut créer un index sur les colonnes référantes, c'est à dira dans ton cas :
* villesfinales.NomComplet
* villestcd.Nom
* villesfinales.CodeRegion
* villestcd.CodeRegion
Bourinho
Salut,

J'ai lu que les index n'était pas efficace s'il y avait peu de possibilités pour une valeur (dans mon cas, je prendrais l'exemple de CodeRegion : 24 possibilités). C'est "pas efficace" (=perte de temps) ou "moins efficace" (=gain de temps moindre que pour un nombre de possibilités plus élevé!). Je penche pour la seconde solution mais c'était juste pour chipoter... wink.gif

Merci
Jeromnimo
Je pense que le problème est légèrement différent du fait que tu fais une jointure avec une autre table.
De toute façon, il faut indexer le code région pour tes ~37 000 valeurs dans ta table de ville, c'est la que sera la différence ;-) Au lieu de parcourir la table, il se servira de l'index :-P
Bourinho
Et dire qu'avant j'attendais plus de 3 heures à chaque fois que je lançais ce genre de requête... j'en rigole maintenant!!! tongue.gif

Je pense que je vais vraiment m'intéresser aux index, car cela ne semble pas très sorcier de bien les choisir et cela permet de soulager grandement le serveur...

A+ et encore merci pour tous ces renseignements!
Ceci est une version "bas débit" de notre forum. Pour voir la version complète avec plus d'information, la mise en page et les images, veuillez cliquer ici.