2017-01-27 2 views
0

Je tente d'obtenir un résultat d'informations de ligne provenant de tables nommées book_info et copy_info, puis (si elles existent) d'une table nommée publisher (dont la clé étrangère est dans copy_info), et (s'ils existent) résultent d'un genre de nom de table via une table de jonction appelée books_genres. Ci-dessous, $ safe_copy_id est défini dans une instruction php, je l'ai laissé pour l'exemple.

Cela fonctionne:Plusieurs jointures travaillant indépendamment mais pas ensemble

SELECT * FROM book_info, copy_info 
LEFT OUTER JOIN publisher ON copy_info.publisher_id = publisher.publisher_id 
WHERE book_info.book_id = copy_info.book_id 
AND copy_info.copy_id = $safe_copy_id LIMIT 1 

et cela fonctionne:

SELECT * FROM book_info, copy_info, books_genres 
LEFT OUTER JOIN genre ON books_genres.genre_id = genre.genre_id 
WHERE book_info.book_id = copy_info.book_id 
AND copy_info.copy_id = $safe_copy_id LIMIT 1 

Mais ce que je voudrais vraiment travailler est la suivante:

SELECT * FROM book_info, copy_info, books_genres 
LEFT OUTER JOIN publisher ON copy_info.publisher_id = publisher.publisher_id 
LEFT OUTER JOIN genre ON books_genres.genre_id = genre.genre_id 
WHERE book_info.book_id = copy_info.book_id 
AND copy_info.copy_id = $safe_copy_id LIMIT 1 

Est-ce que je devrais nicher quelque chose ici? Je ne sais pas comment aller de l'avant et j'apprécierais tout aperçu.

+3

Règle simple: * Jamais * utiliser des virgules dans la clause 'FROM'. * Toujours * utiliser une syntaxe 'JOIN' correcte et explicite. Cela va probablement résoudre votre problème. –

+0

@GordonLinoff J'ai supprimé les virgules de la clause FROM. Je ne suis pas sûr si c'est ce que vous vouliez dire, mais j'ai enlevé "LEFT OUTER" de chaque clause de jointure pour simplement dire JOIN. Cela n'a pas fonctionné malheureusement. –

+0

Je ne suis pas sûr de savoir comment la deuxième requête fonctionne. Il n'y a pas de condition de jointure pour 'books_genres' avec 'book_info' ou' copy_info'. Cherchez-vous un produit cartésien de 'book_genres'? Il serait utile si vous donnez 2 lignes pour toutes les tables et votre résultat attendu basé sur cela. – Utsav

Répondre

0

utiliser juste JOIN correctement:

SELECT * 
FROM book_info bi JOIN 
    copy_info ci 
    ON bi.book_id = ci.book_id JOIN 
    publisher p 
    ON ci.publisher_id = p.publisher_id JOIN 
    books_genres bg 
    ON bg.book_id = bi.book_id JOIN -- your question doesn't specify the JOIN condition here 
    genre g 
    ON bg.genre_id = g.genre_id 
WHERE ci.copy_id = $safe_copy_id 
LIMIT 1; 

Il vous manque une jointure à book_genres. Peut-être est-il lié à book_info.

En outre, je ne vois aucune raison d'utiliser des jointures externes pour la requête. Je soupçonne que toutes les tables ont des relations de clé étrangère valides.

+0

Vous avez raison de dire que livres_genres est lié à l'information de livre, j'ai essayé d'exécuter cette requête exacte avec les ?? remplacés par le lien correct et il échoue toujours. Merci de bien vouloir corriger ma syntaxe. –

+0

J'ai utilisé des jointures externes car tous les éléments copy_id n'auront pas de lignes renvoyées par l'éditeur ou les tables de genre. Je ne suis pas sûr spécifiquement pourquoi mais il renvoie null si j'utilise simplement JOIN, alors que si j'utilise la jointure externe, il ne renvoie que null pour la colonne spécifique (genre_id pour un exemple). C'est ma meilleure explication de mon expérience, je ne sais pas si c'est l'utilisation correcte des jointures externes. –

+0

@KaariLandry. . . Cela semble raisonnable. Remplacez simplement tous les 'JOIN 'par des' LEFT JOIN's. –

0

Merci à Gordon Linoff et à Utsav d'avoir signalé que je n'avais pas de jointure pour book_genres. Voici la requête qui a réellement fonctionné:

SELECT * FROM 
book_info bi JOIN copy_info ci 
ON bi.book_id = ci.book_id 
LEFT OUTER JOIN publisher p 
ON ci.publisher_id = p.publisher_id 
LEFT OUTER JOIN books_genres bg 
ON bg.book_id = bi.book_id 
LEFT OUTER JOIN genre g 
ON bg.genre_id = g.genre_id 
WHERE ci.copy_id = $safe_copy_id 
LIMIT 1;