【问题标题】:2 Left joins put together multiplying the results. But it shouldn't2 左连接放在一起乘以结果。但它不应该
【发布时间】:2016-10-24 04:56:43
【问题描述】:

我正在建立一个聊天网站并向观众展示聊天内容,我有 3 个下拉列表 - 体育(默认为所有体育)、日/月/年、在线用户/总用户。

现在,如果默认选择所有运动,我选择 1 个月和总用户,预期结果应该是

我的查询是

SELECT DISTINCT roo.[Sports], 
                roo.[Name], 
                COUNT(DISTINCT chu.ChatUserLogId) AS TotalUsers, 
                COUNT(DISTINCT liu.[LoggedInUserID]) AS UserOnline

 FROM Room AS roo 

 LEFT JOIN LoggedInUser AS liu ON roo.RoomID = liu.RoomID 
 LEFT JOIN ChatUserLog  AS chu ON roo.RoomID = chu.RoomID 
               AND chu.LoggedInTime >= DATEADD(DAY,-30,GETDATE()) 

 GROUP BY roo.[Sports], roo.[Name]   
 ORDER BY TotalUsers DESC

有人建议用我的方法实际上是因为两个连接而将行相乘,所以我需要先聚合,然后再连接。

所以最后我也尝试了这个查询

with agg_ChatUserLog as (select RoomId, count(*) as cnt_user_tot from ChatUserLog WHERE LoggedInTime >= DATEADD(DAY,-30,GETDATE()) group by RoomId),                                            

       agg_LoggedInUser as (select RoomId, count(*) as cnt_user_logged from LoggedInUser group by RoomId)

select Sports, Name, cnt_user_tot, cnt_user_logged from Room r 

       left outer join agg_ChatUserLog acu on acu.RoomId = r.RoomId 

       left outer join agg_LoggedInUser alu on alu.RoomId = r.RoomId;

但这也使结果成倍增加。

我在两个查询中都犯了哪些错误?在此先感谢您,祝您有美好的一天。

样本数据是:

Chatroom name   Total Users   Online users               

Basketball
Roomname27          32              5
Roomname11          15              3
Roomname32           8              1 

Football
Roomname5           63              12
Roomname18          44               7
Roomname4           15               2

【问题讨论】:

  • 第二种方法看起来不错。添加示例数据和我们将检查的第二个查询结果
  • 在未发表评论的问题中
  • @Prdp 我已在问题中添加了示例供您参考。感谢并期待您的帮助。
  • 这是样本输出。
  • 我已经在问题本身的前面添加了所有表模式。你还需要什么吗?请告诉我您是否需要考虑第二个查询来解决此问题。谢谢

标签: sql sql-server join left-join


【解决方案1】:

您可以尝试其他语法:

select Sports, 
    Name, 
    coalesce(
        ( 
            select count(distinct C.ChatUserLogId) 
            from ChatUserLog as C
            where C.RoomId = R.RoomId 
              and C.LoggedInTime >= DATEADD(DAY,-30,GETDATE()) 
        ), 
    0) AS TotalUsers,
    coalesce(
        (
            select count(distinct D.LoggedInUserID)
            from LoggedInUser as D
            where D.RoomId = R.RoomId 
        ),
    0) AS UserOnline
from Room R 

使用这种语法,您得到的结果永远不会超过房间名称的数量。 但你也有没有观众的房间

【讨论】:

  • 这就是我们一开始的编码方式......但这让情况变得更糟。当有任何在线用户时,先聚合然后选择数据只会使 Sport 的聊天室重复。但是在您的查询中(以及我们首先尝试的),即使没有在线用户,它也只是重复所有体育的聊天室。在线用户与总用户表相乘。你能猜到为什么会出现这个错误吗?谢谢
  • 我猜也是“GROUP BY”项目的问题......“使用 agg_ChatUserLog 作为(从 ChatUserLog 中选择 RoomId, count() as cnt_user_tot WHERE LoggedInTime >= DATEADD(DAY,- 30,GETDATE()) group by RoomId), agg_LoggedInUser as (select RoomId, count() as cnt_user_logged from LoggedInUser group by RoomId) select Sports, Name, cnt_user_tot, cnt_user_logged from Room r left outer join agg_ChatUserLog acu on acu .RoomId = r.RoomId 左外连接 agg_LoggedInUser alu on alu.RoomId = r.RoomId GROUP BY Sports, cnt_user_tot ORDER BY cnt_user_tot DESC"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-06
  • 2011-02-23
  • 2017-12-08
  • 1970-01-01
相关资源
最近更新 更多