Left Join 2 таблицы на 1 столе - PullRequest
3 голосов
/ 13 октября 2011

Это должно быть довольно легко, но я не могу придумать никакого решения и не могу найти ответ где-нибудь ...

Я получил таблицу «пользователи»
и одну таблицу «блоги»(user_id, blogpost)
и одна таблица 'messages' (user_id, message)

Я хотел бы получить следующий результат:

User | count(blogs) | count(messages)  
Jim | 0 | 3  
Tom | 2 | 3  
Tim | 0 | 1  
Foo | 2 | 0

Итак, что я сделал:

SELECT u.id, count(b.id), count(m.id) FROM `users` u  
LEFT JOIN blogs b ON b.user_id = u.id  
LEFT JOIN messages m ON m.user_id = u.id  
GROUP BY u.id

Очевидно, что это не работает, поскольку второе левое объединение относится к блогам, а не к пользователям.Есть предложения?

Ответы [ 2 ]

3 голосов
/ 13 октября 2011

Во-первых, если вам нужно только значение счетчика, вы можете выполнить подвыборы:

select u.id, u.name, 
    (select count(b.id) from blogs where userid = u.id) as 'blogs',
    (select count(m.id) from messages where userid = u.id) as 'messages'
from 'users'

Обратите внимание, что это простой пример sql, у меня нет mysql db, чтобы проверить его прямо сейчас.

С другой стороны, вы можете выполнить объединение, но вы должны использовать outer join, чтобы включить пользователей без блогов, но с сообщениями. Это подразумевает, что вы получаете несколько пользователей несколько раз, поэтому будет полезна группировка по.

1 голос
/ 13 октября 2011

Если вы используете агрегатную функцию для выбора, SQL свернет все ваши строки в одну строку.
Чтобы получить более 1 строки, вы должны использовать предложение group by.
Затем SQLбудет генерировать итоги для каждого пользователя.

Самый быстрый вариант

SELECT 
  u.id
  , (SELECT(COUNT(*) FROM blogs b WHERE b.user_id = u.id) as blogcount
  , (SELECT(COUNT(*) FROM messages m WHERE m.user_id = u.id) as messagecount
FROM users u   

Почему ваш код не работает

SELECT u.id, count(b.id), count(m.id) 
FROM users u   
LEFT JOIN blogs b ON b.user_id = u.id       <<-- 3 matches multiplies # of rows *3
LEFT JOIN messages m ON m.user_id = u.id    <<-- 5 matches multiplies # of rows *5
GROUP BY u.id 

Счет будет выключен, потому что вы подсчитываете повторяющиеся элементы.

Простое исправление, но оно будет медленнее, чем вариант 1
Если вы будете считать только разные идентификаторы, вы получите правильныйрассчитывает:

SELECT u.id, count(DISTNICT b.id), count(DISTINCT m.id) 
FROM users u   
LEFT JOIN blogs b ON b.user_id = u.id     
LEFT JOIN messages m ON m.user_id = u.id    
GROUP BY u.id 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...