65 votes

MySQL : jointures multiples à gauche

J'essaie de créer une page de nouvelles pour un site web sur lequel je travaille. J'ai décidé que je voulais utiliser des requêtes MySQL correctes (c'est-à-dire COUNT(id) et des jointures au lieu de plusieurs requêtes ou de num_rows). J'utilise un wrapper PDO, qui devrait fonctionner correctement, et cela échoue toujours lorsqu'il est exécuté directement par l'application MySQL CLI.

En gros, j'ai 3 tables. L'une contient les nouvelles, l'autre les commentaires et la dernière les utilisateurs. Mon objectif est de créer une page qui affiche tous les titres, les corps, les auteurs et les dates des articles (la pagination se fera plus tard). Cela a bien fonctionné lorsque j'ai utilisé une deuxième requête pour obtenir le nom d'utilisateur, mais j'ai ensuite décidé que je préférais utiliser un JOIN.

Alors quel est le problème ? Eh bien, j'ai besoin de deux jointures. L'une pour obtenir le nom d'utilisateur de l'auteur et l'autre pour obtenir le nombre de commentaires. Lorsque je cherche simplement le nom d'utilisateur de l'auteur, tout fonctionne comme prévu. Toutes les lignes (il y en a 2) du tableau des nouvelles sont affichées. Cependant, lorsque j'ai ajouté ce deuxième LEFT JOIN pour la ligne des commentaires, je finis par ne recevoir qu'une seule ligne de news (rappelez-vous, il y en a 2) et COUNT(comments.id) me donne 2 (il devrait en afficher 1, car j'ai un commentaire pour chaque message).

Qu'est-ce que je fais de mal ? Pourquoi n'affiche-t-il qu'un seul message et indique-t-il qu'il contient deux commentaires, alors qu'il y a deux messages, chacun contenant un commentaire ?

SELECT news.id, users.username, news.title, news.date, news.body, COUNT(comments.id)
FROM news
LEFT JOIN users
ON news.user_id = users.id
LEFT JOIN comments
ON comments.news_id = news.id

Aussi, juste pour être sûr d'une autre chose, ma jointure gauche aux commentaires est la manière correcte d'obtenir tous les messages, qu'ils aient des commentaires ou non, correct ? Ou est-ce que ce serait une jointure à droite ? Oh, une dernière chose... si je passe de comments.news_id = news.id à news.id = comments.news_id, j'obtiens 0 résultat.

116voto

Mark Byers Points 318575

Il vous manque une clause GROUP BY :

SELECT news.id, users.username, news.title, news.date, news.body, COUNT(comments.id)
FROM news
LEFT JOIN users
ON news.user_id = users.id
LEFT JOIN comments
ON comments.news_id = news.id
GROUP BY news.id

La jointure gauche est correcte. Si vous utilisiez une jointure INNER ou RIGHT JOIN, vous n'obtiendriez pas de nouvelles sans commentaires.

0 votes

Devez-vous utiliser le groupe par ? Ma double jointure de débutant ne fonctionne pas, et j'essaie de trouver pourquoi.

0 votes

Merci - cela m'a aidé à résoudre un problème qui était assez difficile pour que je passe 3 heures - résolu en quelques minutes seulement.

7voto

rizon Points 2751

Pour afficher tous les détails pour chaque titre d'article de presse, c'est-à-dire "news.id" qui est la clé primaire, vous devez utiliser la clause GROUP BY pour "news.id".

SELECT news.id, users.username, news.title, news.date,
       news.body, COUNT(comments.id)
FROM news
LEFT JOIN users
ON news.user_id = users.id
LEFT JOIN comments
ON comments.news_id = news.id
GROUP BY news.id

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X