1/ Le champ "id" dans ta table de jointure est inutile et apporte un problème : obligé d'éjouter une contrainte supplémentaire pour vérifier l'unicité des deux colonnes (idutilisateur, idsite). Il doit donc être supprimé au profit d'une clé composite sur (idutilisateur, idsite).
2/ T'es sur la bonne piste, mais c'est pas tout à fait ça
Je suis bien d'accord que c'est pas très clair, et c'est pour ça que je vais t'expliquer plutôt que de te donner la réponse
Le principe de la jointure externe (outer join) c'est de récupérer tous les éléments d'une table, associés aux éléments d'une seconde table, que la jointure soit vraie ou non.
Exemple : Je veux la liste de tous les clients, ainsi que les numéros de commande s'ils en ont.
Code :
SELECT cli.nom, cde.numero, cde.etat FROM client cli LEFT OUTER JOIN commande cde ON cde.client_id = cli.id
|
Résultat :
dupont 123456 C
dupont 654321 V
durant 897456 V
dutronc <null> <null>
|
Maintenant, je veux afiner. En fait, je veux la même chose (tous les clients) mais je n'ai que faire des commandes validée, je ne veux que les commande clôturées.
Naïvement, on sera tenté de rajouter dans la clause WHERE un filtre :
Code :
SELECT cli.nom, cde.numero, cde.etat FROM client cli LEFT OUTER JOIN commande cde ON cde.client_id = cli.id WHERE cde.etat = 'C'
|
Pas de chance... Autant V est effectivement différent de C, autant <null> l'est tout autant !
On a un peu perdu l'intérêt de faire la jointure ouverte.
On se rend compte en fait que ce filtre sur l'état de la commande fait partie non pas du filtre des résultats, mais du critère de jointure entre la table physique "client" et la table logique "commandes clôtuées".
Du coup, voici la bonne syntaxe :
Code :
SELECT cli.nom, cde.numero, cde.etat FROM client cli LEFT OUTER JOIN commande cde ON cde.client_id = cli.id AND cde.etat = 'C'
|
Résultat :
dupont 123456 C
durant <null> <null>
dutronc <null> <null>
|
Ca correspond exactement à ce qu'on voulait.
Maintenant, toi, ce que tu veux, c'est pas vraiment tous les clients, mais tous les clients qui ne répondent pas à la jointure.
Dans notre cas, c'est durant et dutronc.
Là, on se rend compte que si la jointure est bonne, c'est le filtre qui n'est pas bon : on ne veut garder que ceux qui ont cde.numero à null.
Ce qui donne donc :
Code :
SELECT cli.nom, cde.numero, cde.etat FROM client cli LEFT OUTER JOIN commande cde ON cde.client_id = cli.id AND cde.etat = 'C' WHERE cde.numero IS NULL
|
Résultat :
durant <null> <null>
dutronc <null> <null>
|
Message édité par MagicBuzz le 03-07-2007 à 21:04:02