【问题标题】:Left Join 2 tables on 1 table左联接 1 个表上的 2 个表
【发布时间】:2011-10-13 14:57:59
【问题描述】:

这一定很容易,但我想不出任何解决方案,也无法在某处找到答案......

我得到了“用户”表
和一张表“博客”(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

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

【问题讨论】:

    标签: mysql left-join multiple-tables


    【解决方案1】:

    首先,如果你只想要计数值,你可以做子选择:

    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 来包含没有博客但有消息的用户。这意味着您会多次获得多个用户,因此 group by 会很有帮助。

    【讨论】:

    • @user993692 - 这取决于子查询。现代数据库足够智能,可以优化子选择,在这种情况下,您只需要一个非常轻量级的键搜索(假设您没有千万亿用户)。
    【解决方案2】:

    如果您在选择中使用聚合函数,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 
    

    【讨论】:

    • 我已经收到了group by,只是忘了把它写下来。但是结果还是错了,应该是:User | count(blogs) | count(messages) Jim | 0 | 0 Tom | 2 | 2 Tim | 0 | 0 Foo | 2 | 2
    猜你喜欢
    • 1970-01-01
    • 2011-06-30
    • 1970-01-01
    • 2012-07-28
    • 2016-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多