2011-10-13 75 views
3

它必须是很容易的,但我不认为任何解决方案中也可以找到答案的地方...左加入2和表1个表

我得到了表“用户”
和一个表 '博客'(USER_ID,博文)
和一个表 '消息'(USER_ID,消息)

我想有以下结果:

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 

它显然不起作用,因为第二个左连接涉及博客而不是用户。有什么建议么?

回答

3

首先,如果你只想要计数值,你可以做的子查询:

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数据库,现在对它进行测试。

另一方面,您可以加入,但您应该使用outer join以包含没有博客但带有消息的用户。这意味着你多次获得多个用户,所以一个小组将会有所帮助。

+0

+1子选择是最好和最快的选择。 – Johan

+0

好的,谢谢你们!我一直认为子语是邪恶的。 – user993692

+0

@ user993692 - 取决于子查询。现代数据库足够聪明,可以优化子查询,在这种情况下,您只需要一个关键搜索,这非常轻便(假设您没有数十万用户)。 – z00l

1

如果在select中使用聚合函数,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
慢如果只算不同的ID,你会得到正确的计数:

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 
+0

我已经拿到了'group by',只是忘了写下来。但结果仍然是错误的,看起来像: '用户|计数(博客)|计数(消息) Jim | 0 | 0 Tom | 2 | 2 Tim | 0 | 0 Foo | 2 | 2' – user993692

+0

thx为您解释! – user993692