2009-08-09 8 views
3

En essayant de sélectionner une table avec plusieurs jointures, une pour le nombre de commentaires utilisant COUNT et une pour sélectionner la valeur de vote total en utilisant SUM, le problème est que les deux jointures s'influencent mutuellement, au lieu de démontrant:mysql: problème de jointure multiple

3 votes 2 commentaires

Je reçois 3 * 2 = 6 votes et 2 * 3 commentaires

Ceci est la requête que je utilise:

SELECT t.*, COUNT(c.id) as comments, COALESCE(SUM(v.vote), 0) as votes 
FROM (topics t) 
LEFT JOIN comments c ON c.topic_id = t.id 
LEFT JOIN votes v ON v.topic_id = t.id 
WHERE t.id = 9 

Répondre

3

Ce que vous faites est un anti-SQL que j'appelle machine Goldberg. Pourquoi rendre le problème beaucoup plus difficile en le forçant à être fait dans une seule requête SQL?

Voici comment je voudrais vraiment résoudre ce problème:

SELECT t.*, COUNT(c.id) as comments 
FROM topics t 
LEFT JOIN comments c ON c.topic_id = t.id 
WHERE t.id = 9; 

SELECT t.*, SUM(v.vote) as votes 
FROM topics t 
LEFT JOIN votes v ON v.topic_id = t.id 
WHERE t.id = 9; 

Comme vous l'avez trouvé, la combinaison de ces deux en un des résultats de la requête dans un produit cartésien. Il peut y avoir des manières intelligentes et subtiles de le forcer à vous donner la réponse correcte dans une requête, mais que se passe-t-il quand vous avez besoin d'une troisième statistique? Il est beaucoup plus simple de le faire dans deux requêtes.

+0

Cela ne se traduira-t-il pas par plus de chargement et plus de travail pour la base de données ou est-il plus difficile pour la base de données de travailler avec plusieurs jointures puis de les séparer? – Dennis

+0

La plupart des bases de données possèdent une mise en cache interne pour les pages de données et d'index, ce qui ne pose donc pas de problème. De plus, le travail nécessaire pour compenser le produit cartésien peut être pire. En partie cela dépend de votre système spécifique et de vos données, donc la réponse la plus précise nécessite un test dans * votre * environnement. –

0
SELECT t.*, COUNT(DISTINCT c.id) as comments, COALESCE(SUM(v.vote), 0) as votes 
FROM (topics t) 
LEFT JOIN comments c ON c.topic_id = t.id 
LEFT JOIN votes v ON v.topic_id = t.id 
WHERE t.id = 9 
+0

Je reçois maintenant le bon nombre de commentaires mais je reçois toujours une somme incorrecte des votes, j'ai essayé d'ajouter DISTINCT à v.vote aussi, mais cela n'a pas fonctionné. – Dennis

1
SELECT t.*, COUNT(c.id) as comments, COALESCE(SUM(v.vote), 0) as votes 
FROM (topics t) 
LEFT JOIN comments c ON c.topic_id = t.id 
LEFT JOIN votes v ON v.topic_id = t.id 
WHERE t.id = 9 
GROUP BY t.id 

ou peut-être

SELECT `topics`.*, 
(
    SELECT COUNT(*) 
    FROM `comments` 
    WHERE `topic_id` = `topics`.`id` 
) AS `num_comments`, 
(
    SELECT IFNULL(SUM(`vote`), 0) 
    FROM `votes` 
    WHERE `topic_id` = `topics`.`id` 
) AS `vote_total` 
FROM `topics` 
WHERE `id` = 9 
Questions connexes