OVH Cloud OVH Cloud

jointure mal faite ?

9 réponses
Avatar
Aurélien Barbier-Accary
Bonjour,

j'ai deux tables :
- une table d'auteurs qui contient notamment leur nom
- une table de publications qui contient entre autres l'identifiant d'un
auteur et éventuellement de 2 autres co-auteurs (NULL si ils n'existent pas)

Je souhaite afficher pour chaque publication le nom de chacun des co-auteurs.
Pour cela j'effectue la requête suivante :

SELECT DISTINCT pub.titre, aut.nom, coaut1.nom, coaut2.nom
FROM `phpsgbiblio_publications` pub, `phpsgbiblio_auteurs` aut,
`phpsgbiblio_auteurs` coaut1, `phpsgbiblio_auteurs` coaut2
WHERE aut.id = pub.auteur
AND coaut1.id = pub.coauteur1
AND coaut2.id = pub.coauteur2;

Cependant je n'obtiens des réponses que pour les publications qui ont bien 3
co-auteurs, mais pas celles pour lesquelles il n'y a qu'un ou deux auteurs :-(

J'ai essayé de remplacer les clauses dans le WHERE par
AND(pub.coauteur1=NULL OR coaut1.id=pub.coauteur1)
mais ça ne fonctionne pas non plus.

Quelqu'un peut-il m'aiguiller ?
Merci d'avance.
Aurélien.

PS: j'utilise MySQL mais là je crois que cest plus un problème de concept général...

9 réponses

Avatar
Aurélien Barbier-Accary
helios a écrit :
"Aurélien Barbier-Accary" a écrit
mais n'y a-t-il pas plus simple ?
Le souci c'est qu'en vrai il peut y avoir jusqu'à 8 co-auteurs et que pour
chacun je veux récupérer différentes informations. Ma requête va faire 10
kilomètres de long ! Peut-on simplifier un peu tout ça ?

Aurélien.



ce probleme est un classique dans les SGBDR qui gere les mediatheques et les
mediatheques sont a 90% sur le meme type de SGBD les SGBDMV car ils contient
la solution de maniere simple :

Dr Thierry HOLZ
helios services
180 rue de la croix du chene
60250 HEILLES
www.openqm.be
www.sgbdmv.be
www.sgbdr.be




??? je n'ai pas tout compris là. Ne manque-t-il pas la fin de votre message
après les deux points ?

Alors essayons de voir si j'ai bien saisi le début :
- SGBD: Système Généralisé de Base de Données
- SGBDR: SGBD Relationnelles
- SGBDMV: SGBD Multi-Valuées
J'ai bon jusque là ?

Je n'ai pas bien saisi en quoi ça peut me mettre sur la voie d'une solution plus
simple... (je précise que je suis complètement ignare en BdD) Enfin comme on dit
c'est l'intention qui compte, alors merci quand même.

Aurélien.
Avatar
Aurélien Barbier-Accary
Merci pour la réponse.
Mais elle appelle d'autres questions (ci-dessous)...

Patrick Mevzek a écrit :
Le Sun, 19 Mar 2006 12:45:23 +0100, Aurélien Barbier-Accary a écrit :
Je souhaite afficher pour chaque publication le nom de chacun des co-auteurs.
Pour cela j'effectue la requête suivante :



Il manque le mot-clef JOIN



ou cela ? Ma solution qui n'utilise pas ce mot clef est-elle donc mauvaise ? Si
oui en quoi ?

J'ai essayé de remplacer les clauses dans le WHERE par
AND(pub.coauteur1=NULL OR coaut1.id=pub.coauteur1)



=NULL n'est pas possible, c'est IS NULL la syntaxe correcte.



oui, ça je viens de le trouver mais finalement j'avais trouvé une solution
contournant ce problème.
Maintenant je cherche à simplifier mon écriture qui me parait relever plus de la
bidouille que de quelque chose de sérieux...
Avatar
Aurélien Barbier-Accary
Aurélien Barbier-Accary a écrit :
Patrick Mevzek a écrit :
Il manque le mot-clef JOIN



ou cela ? Ma solution qui n'utilise pas ce mot clef est-elle donc
mauvaise ? Si oui en quoi ?




Bon apparemment je fais un produit cartésien et pas une jointure.
cf http://mysql.developpez.com/faq/?page=SYNTAXE_JOINTURES

Merci encore pour l'info Patrick.
Avatar
Jacques Caron
Salut,

On Sun, 19 Mar 2006 12:45:23 +0100, Aurélien Barbier-Accary
wrote:

j'ai deux tables :
- une table d'auteurs qui contient notamment leur nom
- une table de publications qui contient entre autres l'identifiant
d'un auteur et éventuellement de 2 autres co-auteurs (NULL si ils
n'existent pas)

Je souhaite afficher pour chaque publication le nom de chacun des
co-auteurs.
Pour cela j'effectue la requête suivante :

SELECT DISTINCT pub.titre, aut.nom, coaut1.nom, coaut2.nom
FROM `phpsgbiblio_publications` pub, `phpsgbiblio_auteurs` aut,
`phpsgbiblio_auteurs` coaut1, `phpsgbiblio_auteurs` coaut2
WHERE aut.id = pub.auteur
AND coaut1.id = pub.coauteur1
AND coaut2.id = pub.coauteur2;

Cependant je n'obtiens des réponses que pour les publications qui ont
bien 3 co-auteurs, mais pas celles pour lesquelles il n'y a qu'un ou
deux auteurs :-(



Normal.

Quelqu'un peut-il m'aiguiller ?



LEFT JOIN est là pour ça:

SELECT pub.titre, aut.nom, coaut1.nom, coaut2.com
FROM publications pub
JOIN auteurs aut ON (pub.auteur=aut.id)
LEFT JOIN auteurs coaut1 ON (pub.coauteur1 = coaut1.id)
LEFT JOIN auteurs coaut2 ON (pub.coauteur2 = coaut2.id);

PS: j'utilise MySQL mais là je crois que cest plus un problème de
concept général...



On va supposer que MySQL implémente LEFT JOIN :-)

Jacques.
--
Oxado http://www.oxado.com/
Avatar
William Marie
"Jacques Caron" a écrit dans le message de news:


On va supposer que MySQL implémente LEFT JOIN :-)



Ca serait malheureux ! Access 2003 le fait très bien et dans son
gros casse-croute (chez Micro-Application) Hervé Inissan donne un cas
tout à fait semblable pour illustrer l'utilisation de LEFT JOIN.
--
========================================================== William Marie
Toulouse (France)
mailto:
ATTENTION ! Anti-SPAM pour m'écrire remplacer trapellun.net
par free.fr
http://wmarie.free.fr
===========================================================
Avatar
Ph. B.
Aurélien Barbier-Accary a demandé:
Bonjour,

j'ai deux tables :
- une table d'auteurs qui contient notamment leur nom
- une table de publications qui contient entre autres l'identifiant
d'un auteur et éventuellement de 2 autres co-auteurs (NULL si ils
n'existent pas)

Je souhaite afficher pour chaque publication le nom de chacun des
co-auteurs.
Pour cela j'effectue la requête suivante :

SELECT DISTINCT pub.titre, aut.nom, coaut1.nom, coaut2.nom
FROM `phpsgbiblio_publications` pub, `phpsgbiblio_auteurs` aut,
`phpsgbiblio_auteurs` coaut1, `phpsgbiblio_auteurs` coaut2
WHERE aut.id = pub.auteur
AND coaut1.id = pub.coauteur1
AND coaut2.id = pub.coauteur2;

Cependant je n'obtiens des réponses que pour les publications qui ont
bien 3 co-auteurs, mais pas celles pour lesquelles il n'y a qu'un ou
deux auteurs :-(



C'est normal. tu as réalisé un produit cartésien sur tes tables, et la
clause de filtrage (WHERE ... AND ...) que tu as mise en place ne peut
te renvoyer que les cas où les 3 auteurs sont renseignés.

Il te faut utiliser une jointure externe gauche (LEFT JOIN...) sur ta
table des auteurs.

J'ai essayé de remplacer les clauses dans le WHERE par
AND(pub.coauteur1=NULL OR coaut1.id=pub.coauteur1)
mais ça ne fonctionne pas non plus.



Null n'est pas une valeur en soi mais indique une absence de valeur...
Dans ce ca, l'égalité ne peut être utilisée, mais l'expression "IS NULL"
oui...

Quelqu'un peut-il m'aiguiller ?
Merci d'avance.
Aurélien.

PS: j'utilise MySQL mais là je crois que cest plus un problème de
concept général...



Tout à fait, c'est plus un problème de raisonnement ensembliste...

Pour les jointures, regardes ici:
http://sql.developpez.com/sqlaz/jointures/

Pour les valeurs NULL, regardes ici:
http://sql.developpez.com/null/

Enfin pour ton problème, la solution est comme je l'ai dit plus haut
d'utiliser des jointures externes gauches:

SELECT pub.titre, aut.nom, coaut1.nom, coaut2.nom
FROM `phpsgbiblio_publications` pub
LEFT JOIN `phpsgbiblio_auteurs` aut ON pub.auteur = aut.id
LEFT JOIN `phpsgbiblio_auteurs` coaut1 ON pub.coauteur1 = coaut1.id
LEFT JOIN `phpsgbiblio_auteurs` coaut2 ON pub.coauteur2 = coaut2.id

Une solution à base de sous-requêtes est possible mais fortement
déconseillée du point de vue des performances:

SELECT pub.titre,
(SELECT aut.nom FROM `phpsgbiblio_auteurs` aut
WHERE id = pub.auteur),
(SELECT coaut1.nom FROM `phpsgbiblio_auteurs` coaut1
WHERE coaut1.id = pub.coauteur1),
(SELECT coaut2.nom FROM `phpsgbiblio_auteurs` coaut2
WHERE coaut2.id = pub.coauteur2)
FROM `phpsgbiblio_publications`

--
Philippe.
Avatar
Ph. B.
Ph. B. wrote:
Aurélien Barbier-Accary a demandé:
Bonjour,

j'ai deux tables :
- une table d'auteurs qui contient notamment leur nom
- une table de publications qui contient entre autres l'identifiant
d'un auteur et éventuellement de 2 autres co-auteurs (NULL si ils
n'existent pas)

Je souhaite afficher pour chaque publication le nom de chacun des
co-auteurs.
Pour cela j'effectue la requête suivante :

SELECT DISTINCT pub.titre, aut.nom, coaut1.nom, coaut2.nom
FROM `phpsgbiblio_publications` pub, `phpsgbiblio_auteurs` aut,
`phpsgbiblio_auteurs` coaut1, `phpsgbiblio_auteurs` coaut2
WHERE aut.id = pub.auteur
AND coaut1.id = pub.coauteur1
AND coaut2.id = pub.coauteur2;

Cependant je n'obtiens des réponses que pour les publications qui ont
bien 3 co-auteurs, mais pas celles pour lesquelles il n'y a qu'un ou
deux auteurs :-(



C'est normal. tu as réalisé un produit cartésien sur tes tables, et la
clause de filtrage (WHERE ... AND ...) que tu as mise en place ne peut
te renvoyer que les cas où les 3 auteurs sont renseignés.

Il te faut utiliser une jointure externe gauche (LEFT JOIN...) sur ta
table des auteurs.

J'ai essayé de remplacer les clauses dans le WHERE par
AND(pub.coauteur1=NULL OR coaut1.id=pub.coauteur1)
mais ça ne fonctionne pas non plus.



Null n'est pas une valeur en soi mais indique une absence de valeur...
Dans ce ca, l'égalité ne peut être utilisée, mais l'expression "IS NULL"
oui...

Quelqu'un peut-il m'aiguiller ?
Merci d'avance.
Aurélien.

PS: j'utilise MySQL mais là je crois que cest plus un problème de
concept général...



Tout à fait, c'est plus un problème de raisonnement ensembliste...

Pour les jointures, regardes ici:
http://sql.developpez.com/sqlaz/jointures/

Pour les valeurs NULL, regardes ici:
http://sql.developpez.com/null/

Enfin pour ton problème, la solution est comme je l'ai dit plus haut
d'utiliser des jointures externes gauches:

SELECT pub.titre, aut.nom, coaut1.nom, coaut2.nom
FROM `phpsgbiblio_publications` pub
LEFT JOIN `phpsgbiblio_auteurs` aut ON pub.auteur = aut.id
LEFT JOIN `phpsgbiblio_auteurs` coaut1 ON pub.coauteur1 = coaut1.id
LEFT JOIN `phpsgbiblio_auteurs` coaut2 ON pub.coauteur2 = coaut2.id

Une solution à base de sous-requêtes est possible mais fortement
déconseillée du point de vue des performances:

SELECT pub.titre,
(SELECT aut.nom FROM `phpsgbiblio_auteurs` aut
WHERE id = pub.auteur),
(SELECT coaut1.nom FROM `phpsgbiblio_auteurs` coaut1
WHERE coaut1.id = pub.coauteur1),
(SELECT coaut2.nom FROM `phpsgbiblio_auteurs` coaut2
WHERE coaut2.id = pub.coauteur2)
FROM `phpsgbiblio_publications`



Attention, j'ai pris le cas où l'auteur et les coauteurs ne sont pas
obligatoires dans ton modèle de données...
Si les auteurs sont obligatoires, il faut écrire:

SELECT pub.titre, aut.nom, coaut1.nom, coaut2.nom
FROM `phpsgbiblio_publications` pub
INNER JOIN `phpsgbiblio_auteurs` aut ON pub.auteur = aut.id
LEFT JOIN `phpsgbiblio_auteurs` coaut1 ON pub.coauteur1 = coaut1.id
LEFT JOIN `phpsgbiblio_auteurs` coaut2 ON pub.coauteur2 = coaut2.id

--
Philippe.
Avatar
helios
"Aurélien Barbier-Accary" a écrit
dans le message de news:441d69c9$0$20856$
helios a écrit :
> "Aurélien Barbier-Accary" a


écrit
>> mais n'y a-t-il pas plus simple ?
>> Le souci c'est qu'en vrai il peut y avoir jusqu'à 8 co-auteurs et que


pour
>> chacun je veux récupérer différentes informations. Ma requête va faire


10
>> kilomètres de long ! Peut-on simplifier un peu tout ça ?
>>
>> Aurélien.
>
> ce probleme est un classique dans les SGBDR qui gere les mediatheques et


les
> mediatheques sont a 90% sur le meme type de SGBD les SGBDMV car ils


contient
> la solution de maniere simple :
>
> Dr Thierry HOLZ
> helios services
> 180 rue de la croix du chene
> 60250 HEILLES
> www.openqm.be
> www.sgbdmv.be
> www.sgbdr.be
>

??? je n'ai pas tout compris là. Ne manque-t-il pas la fin de votre


message
après les deux points ?

Alors essayons de voir si j'ai bien saisi le début :
- SGBD: Système Généralisé de Base de Données
- SGBDR: SGBD Relationnelles
- SGBDMV: SGBD Multi-Valuées
J'ai bon jusque là ?

Je n'ai pas bien saisi en quoi ça peut me mettre sur la voie d'une


solution plus
simple... (je précise que je suis complètement ignare en BdD) Enfin comme


on dit
c'est l'intention qui compte, alors merci quand même.

Aurélien.




SGBD c'est Systeme de Gestion de Base de Données

le fait qu'une oeuvre ai plusieur co auteur est une illustration de
multivaluées

alors deux maniere de resoudre le probleme :

- faire des bidouillages infammes, complexes et aleatoires dans un SGBDR non
MV
- utilise un SGBDR MV plus simplement noté SGBDMV et dans ce cas


si ton fichier d'oeuvre se nomme LIVRES et que les champs titres et auteurs
sont definie comme etant TITRES et AUTEURS

tu tapes une requete MV style

TRIER LIVRES TITRES AUTEURS

et tu obtients par exemple

titre1 auteur1
auteur2
auteur3
auteur4

titre2 auteur2
auteur3

titre3 auteur1

titre4 auteur5


Dr Thierry HOLZ
helios services
180 rue de la croix du chene
60250 HEILLES
www.openqm.be
www.sgbdmv.be
Avatar
Aurélien Barbier-Accary
helios a écrit :
le fait qu'une oeuvre ai plusieur co auteur est une illustration de
multivaluées

alors deux maniere de resoudre le probleme :

- faire des bidouillages infammes, complexes et aleatoires dans un SGBDR non
MV
- utilise un SGBDR MV plus simplement noté SGBDMV et dans ce cas




Merci pour ces explications !
Moi je travaille avec MySQL sous PHP (c'est pour mon site web), donc je crois
que malheureusement je ne peux pas faire de MV, non ?!