2009-08-09 2 views
3

Я пытаюсь выбрать таблицу с несколькими объединениями, одну для количества комментариев с использованием COUNT и одну, чтобы выбрать общее значение для голосования, используя SUM, проблема в том, что эти два объединения влияют друг на друга, а не показ:mysql: проблема с множественным соединением

3 голосов 2 комментария

я получаю 3 * 2 = 6 голосов и 2 * 3 комментарии

Это запрос, я использую:

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 

ответ

3

Что вы делаете это SQL антипаттерн, что я называю Goldberg Machine. Зачем ставить проблему намного сложнее, заставляя ее выполнять в одном SQL-запросе?

Вот как бы я действительно решить эту проблему:

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; 

Как вы нашли, комбинируя эти два в один результат запроса в декартово произведение. Могут быть умные и тонкие способы заставить его дать правильный ответ в одном запросе, но что происходит, когда вам нужна третья статистика? Это намного проще сделать в двух запросах.

+0

Не приведет ли это к большей загрузке и дополнительной работе для базы данных, или это сложнее для базы данных работать с несколькими объединениями, чтобы отделить их? – Dennis

+0

Большинство баз данных имеют внутреннее кэширование для страниц данных и индексов, поэтому это может и не быть проблемой. Кроме того, работа, которая необходима для компенсации декартова продукта, может быть хуже. Отчасти это зависит от вашей конкретной системы и ваших данных, поэтому самый точный ответ требует тестирования в * вашей * среде. –

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

Теперь я получаю правильное количество комментариев, но я все равно получаю неправильную сумму голосов, я пытался добавить DISTINCT к v.vote, но это не сработало. – 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 

или, возможно,

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