Voici ce que je veux accomplir : sélectionnez toutes les lignes du tableau « messages » tout en récupérant également les entités liées, telles que l'auteur (du tableau « utilisateurs ») et les noms des catégories auxquelles appartient le message (à partir du tableau « catégories »).

Ce sont mes deux requêtes jusqu'à présent :
Celui-ci récupère les messages :

SÉLECTIONNER
messages.*
, users.authorName AS auteur
DE messages
utilisateurs INNER JOIN
ON users.id = posts.author

Et celui-ci récupère une liste de catégories séparées par des virgules pour un message spécifique :

SÉLECTIONNER
GROUP_CONCAT(categories.category) AS catégories
DES catégories
INNER JOIN post_category
ON post_category.categoryID = categories.id
O
post_category.postID = ?

Les deux requêtes seules fonctionnent bien.

Naturellement, lorsque les deux sont combinés, je n'aurais pas besoin de la clause WHERE de la deuxième requête. J'ai essayé d'utiliser la deuxième requête comme sous-requête dans la clause SELECT de la première, mais cela a récupéré une liste séparée par des virgules de TOUTES les catégories pour TOUS les messages. Je veux seulement les catégories pour le post sur lequel je suis en train d'itérer.

Toute aide serait grandement appréciée, et je m'excuse si tout cela n'est pas clair - c'est déjà assez difficile pour moi d'y penser, et encore moins de décrire à d'autres personnes ;)

1
Steven Mercatante 29 août 2009 à 00:59

2 réponses

Meilleure réponse

Quelque chose comme ça:

SELECT posts.*, users.authorName AS author,
       GROUP_CONCAT(categories.category) AS categories
  FROM posts, users, categories, post_category
 WHERE users.id = posts.author
   AND post_category.categoryID = categories.id
   AND post_category.postID = posts.id
 GROUP BY posts.* /* list actual columns here */, author

Ou ai-je raté quelque chose?

2
ChssPly76 29 août 2009 à 01:03
Cela a parfaitement fonctionné, merci ! On dirait que j'étais trop compliqué avec les jointures internes.
 – 
Steven Mercatante
29 août 2009 à 01:11
Cela peut fonctionner, mais je soupçonne que vous rencontrerez des problèmes de performances sur la route. Une jointure croisée à 4 voies est une mauvaise idée.
 – 
Peter Ruderman
29 août 2009 à 01:16
Je ne savais pas qu'il y avait des problèmes de performances entre les deux types de jointures. Une recherche rapide sur Google m'a cependant conduit sur cette page de la documentation MySQL (dev .mysql.com/doc/refman/5.0/en/join.html). Il prétend >Dans MySQL, CROSS JOIN est un équivalent syntaxique à INNER JOIN (ils peuvent se remplacer). En SQL standard, ils ne sont pas équivalents. J'espère donc que je ne rencontrerai aucun problème de performances car j'utilise MySQL.
 – 
Steven Mercatante
29 août 2009 à 01:22
- les problèmes de performances à venir, bien que possibles, seraient plus probablement causés par GROUP BY plutôt que par l'adhésion (en supposant, bien sûr, que des index appropriés aient été configurés). La requête que vous avez suggérée dans votre réponse finira par faire la même jointure croisée.
 – 
ChssPly76
29 août 2009 à 01:24

Je pense que votre approche de sous-requête devrait fonctionner correctement, mais vous avez toujours besoin de la clause where dans votre sous-requête. Sinon, comment MySQL saurait-il quelles lignes récupérer ? Essayer:

SELECT posts.*, users.authorName AS author,
    (SELECT GROUP_CONCAT(categories.category) 
     FROM categories
     INNER JOIN post_category ON post_category.categoryID = categories.id
     WHERE post_category.postID = posts.postID) AS categories
FROM posts
INNER JOIN users ON users.id = posts.author
1
Peter Ruderman 29 août 2009 à 01:11