MySQL, jointures multiples, WHERE et psychiatrie

WRInaute accro
Bonjour,

Je deviens complètement fou sur une requête MySQL. :(

Code:
SELECT *
FROM fiches
LEFT JOIN declinaisons ON fiches.iddeclinaison = declinaisons.id
LEFT JOIN carrosseries ON declinaisons.variante = carrosseries.id
LEFT JOIN marques ON fiches.idmarque = marques.id
LEFT JOIN modeles ON fiches.idmodele = modeles.id
LEFT JOIN segments ON modeles.segment = segments.id

Cette requête me renvoie toutes les infos dont j'ai besoin et fonctionne parfaitement.

Mais dès que j'ajoute un WHERE, certains enregistrements sautent ou ne concordent plus 8O
Comment est-ce possible ? A quoi faut il faire attention lors de l'ajout de critères WHERE sur une table avec multiples jointures ?
Le fait que toutes les tables n'aient pas le même nombre de ligne est il en cause ?
Merci
 
WRInaute passionné
Mais dès que j'ajoute un WHERE, certains enregistrements sautent ou ne concordent plus
As tu des exemples..?

Comment est-ce possible ? A quoi faut il faire attention lors de l'ajout de critères WHERE sur une table avec multiples jointures ?
Je ne crois pas... montre voir a quoi ressemble ta requête avec les conditions WHERE?

Le fait que toutes les tables n'aient pas le même nombre de ligne est il en cause ?
non
 
WRInaute accro
Voici un exemple avec WHERE
Code:
SELECT *
FROM fiches
LEFT JOIN declinaisons ON fiches.iddeclinaison = declinaisons.id
LEFT JOIN carrosseries ON declinaisons.variante = carrosseries.id
LEFT JOIN marques ON fiches.idmarque = marques.id
LEFT JOIN modeles ON fiches.idmodele = modeles.id
LEFT JOIN segments ON modeles.segment = segments.id
WHERE modeles.path_modele = 'clio'
AND declinaisons.path_motorisation = '1l5-dci'

Sans le WHERE,les valeurs renvoyées pour les données de la table "declinaisons" sont correctes. Avec un clause WHERE, elle ne sont pas cohérentes ou vides. 8O
 
WRInaute accro
Et si tu fais une simple requête (sans jointure) dans ta table déclinaisons avec un WHERE declinaisons.path_motorisation = '1l5-dci' tu as des données qui te semblent correctes ?
 
WRInaute passionné
Je crois qu'il y a un problème dans ta syntaxe... essayes ça:
SELECT *
FROM fiches
LEFT JOIN declinaisons ON declinaisons.id=fiches.iddeclinaison
LEFT JOIN carrosseries ON carrosseries.id=declinaisons.variante
LEFT JOIN marques ON marques.id=fiches.idmarque
LEFT JOIN modeles ON modeles.id=fiches.idmodele
LEFT JOIN segments ON segments.id=modeles.segment
WHERE modeles.path_modele = 'clio'
AND declinaisons.path_motorisation = '1l5-dci'
 
WRInaute accro
UsagiYojimbo a dit:
Et si tu fais une simple requête (sans jointure) dans ta table déclinaisons avec un WHERE declinaisons.path_motorisation = '1l5-dci' tu as des données qui te semblent correctes ?
Oui, parfaitement correct.

Anto1982 merci ça ne change rien.

Dès que je met une clause where, quelle que soit la table visée, tout ce qui correspond à "declinaisons" part en vrille 8O
 
WRInaute accro
Ca aiderait avec un exemple des données et des résultats obtenus... Je pense que le problème doit être lié à l'utilisation de LEFT JOIN (plutôt que JOIN), mais comme ça, là, je ne vois pas de raison particulière que ça cloche. Tu as effectivement des fiches qui n'ont pas de declinaison/marque/modele correspondants (et pareil declinaison->carrosserie et modele->segment)? Si ce n'est pas le cas, tu n'as pas besoin du LEFT...

Jacques.
 
WRInaute impliqué
Et ça :

Code:
SELECT *
FROM fiches
LEFT JOIN declinaisons ON fiches.iddeclinaison = declinaisons.id AND declinaisons.path_motorisation = '1l5-dci'
LEFT JOIN carrosseries ON declinaisons.variante = carrosseries.id
LEFT JOIN marques ON fiches.idmarque = marques.id
LEFT JOIN modeles ON fiches.idmodele = modeles.id AND modeles.path_modele = 'clio'
LEFT JOIN segments ON modeles.segment = segments.id
 
WRInaute accro
Bonjour Jacques, merci tu as parfaitement raison, question d'habitude, j'en avais oublié l'existence du JOIN seul.
Sans les LEFT ça ne change rien. J crois plutôt qu'il doit y avoir un problème dans une des règles de jointures.
DadouDuck, merci mais ça n'a rien changé... mais j'apprends qu'on peut mettre des critères en plus dans le ON merci !

Malheureusement, donner des exemples de données risque d'être bien compliqué.
 
WRInaute accro
Rien qu'un exemple d'une ligne de données qui ne correspond pas à ce que tu veux pourrait probablement aider.

Jacques.
 
WRInaute passionné
Est-ce que tu pourrais donner un jeu de données (genre: 3 lignes de chaques tables avec au moin un jeu de données qui ne ofnctionne pas dans la requete avec le WHERE)?
 
WRInaute discret
Dès que t'as commencé à parler des jointures externes avec des where, j'ai compris que t'es tombé sur une erreur très courante sur SQL : Mettre les conditions sur les tables secondaires.

En effet, ce n'est pas la faute ni de SQL ni de MySQL mais de compréhension de ton propre besoin. Quand tu fais une jointure externe tab1 left join tab2, tu dis que tu souhaites afficher les données de tab1 en entier, complétée si possible par les données de tab2.

Quand tu ajoutes une conditions sur tab2, ca ne change rien pour le nombre de lignes. Il affiche toujours toute la tab1 et il termine par les données de tab2 qui répondent à la condition.

Si tu ne veux afficher que les lignes avec les données qui correspondent à ta condition alors tu remplaces "LEFT JOIN" par "INER JOIN". Sinon tu parts sur une requêtes imbriquées avec des NOT NULL.
 
WRInaute accro
Merci jamalofski mais j'ai remplacé la requête postée plus haut par des INNER JOIN et ai lancé sans aucun WHERE j'ai très peu de résultat (13 sur 137). Si j'ajoute un WHERE quel qu'il soit, je n'ai plus aucune données renvoyée
 
WRInaute accro
jamalofski a dit:
Quand tu ajoutes une conditions sur tab2, ca ne change rien pour le nombre de lignes. Il affiche toujours toute la tab1 et il termine par les données de tab2 qui répondent à la condition.

Ca, ça dépend d'où tu mets la condition. C'est vrai si tu mets la condition dans le ON, pas dans le WHERE.

Jacques.
 
WRInaute accro
J'ai créé un compte "invité" avec une vingtaine de lignes (échantillon), vous pouvez me MP pour l'accés ;)

Merci à vous.
 
WRInaute accro
milkiway a dit:
Merci jamalofski mais j'ai remplacé la requête postée plus haut par des INNER JOIN et ai lancé sans aucun WHERE j'ai très peu de résultat (13 sur 137). Si j'ajoute un WHERE quel qu'il soit, je n'ai plus aucune données renvoyée

Comme expliqué par MP, c'est parce que tu as beaucoup d'associations invalides (des "fiches" qui font référence à des "declinaisons" qui n'existent pas, etc.). Un JOIN ne renvoie que les lignes pour lesquelles il peut faire toutes les associations. Un LEFT JOIN renvoie toutes les lignes, mais laisse des NULLs là où il ne trouve rien dans les tables "secondaires".

Exemple:
Code:
tablea:
id | idb
---+----
1  | 0
2  | 1

tableb:
id | desc
---+-----
1  | toto

select * from tablea join tableb on (tablea.idb=tableb.id)
id | idb | id | desc
---+-----+----+-----
2  | 1   | 1  | toto

select * from tablea LEFT join tableb on (tablea.idb=tableb.id)
id | idb | id | desc
---+-----+----+-----
1  | 0   |    |
2  | 1   | 1  | toto

(les valeurs de id et desc sur la première ligne sont null)

Jacques.
 
WRInaute accro
Je tiens à remercier toutes les personnes qui sont intervenues sur ce topic pour leur aide. Tous les messages de réponse ont apportés soit une pierre à l'édifice, soit des connaissances que je n'avais pas et ou qui serviront à d'autres.
Je remercie tout particulièrement Anto1982 qui m'a proposé son aide en privé (merci plus besoin, voir la suite) et chaleureusement jcaron pour son aide en privé sur la base (directement dans phpmyadmin) et qui a mis le doigt sur le seul problème depuis le début : ce sont mes données qui sont fausses.
L'erreur vient tout simplement de mon script PHp de conversion de mes données excel en multiples tables SQL, une des valeur de jointure n'était pas affectée correctement.

Maintenant que ces données sont corrigées, tout fonctionne à la perfection.

Vous m'avez tiré une sacré épine du pied, j'en été allé jusqu'à passer 2 jours dessus et imprimer et placarder sur le mur mes tables sans voir le plus évident.................

Merci :'(
 
Discussions similaires
Haut