为什么Count(*)会返回意外的数字?

时间:2012-09-28 13:51:16

标签: sql sql-server sql-server-2008

这是我的疑问:

Select COUNT(*) 
From 
    Users u
    Inner Join 
    UsersLoginHistory uh On u.UserID = uh.UserID 
Where 
    1 = 1   
    And 
    u.AccountID = 37 
Group By u.UserID

我希望能够得到的是Count(*),应该在u.UserId分组后返回一个数字。但它会在群组之前返回Count(*)

所以我可以将上面的查询重写为:

Select COUNT(*)
From (
    Select   u.Username   
    From 
        Users u
        Inner Join 
        UsersLoginHistory uh On u.UserID = uh.UserID 
    Where 
        1 = 1   
        And 
        u.AccountID = 37 
    Group By u.UserID
) v

但是我需要找出为什么在分组之前Count(*)返回记录,以及如何修复第一个查询本身。

编辑:示例记录

用户表

UserId     Username
102        tom.kaufmann

UserLoginHistory表

UsersLoginHistoryID UserID  LoginDateTime         LogoutDateTime         IPAddress
1                    102    2012-09-28 01:16:00 NULL                 115.118.71.248
2                    102    2012-09-28 01:29:00 2012-09-28 01:29:00  127.0.0.1
3                    102    2012-09-28 01:32:00 2012-09-28 01:32:00  127.0.0.1
4                    102    2012-09-28 01:41:00 NULL                 115.118.71.248
5                    102    2012-09-28 01:43:00 2012-09-28 07:04:00  115.118.71.248  

依旧......

Haven写了这个DB中的每一条记录。

5 个答案:

答案 0 :(得分:2)

根据您说的第二个查询返回所需的结果(假设UserIDUsers的PK)我认为这就是您需要的

SELECT Count(UserID)
FROM   Users u
WHERE  u.AccountID = 37
       AND EXISTS (SELECT *
                   FROM   UsersLoginHistory uh
                   WHERE  u.UserID = uh.UserID)

这比扩展所有已连接的行然后再次使用Group By u.UserID折叠它们并计算结果的行数更有效。

答案 1 :(得分:1)

将第一行更改为:

Select COUNT(*), u.UserID

答案 2 :(得分:0)

这应该为您提供用户列表和用户登录历史记录表中的条目数。

SELECT u.UserId
, COUNT(uh.*)
FROM Users u
INNER JOIN UsersLoginHistory uh ON u.UserID = uh.UserID
WHERE u.AccountID = 37
GROUP BY u.UserID

答案 3 :(得分:0)

但是我需要找出为什么Count(*)在分组之前返回记录以及如何修复第一个查询本身

它计算每个UserID的行数(登录次数),这正是group by的工作原理。

答案 4 :(得分:0)

COUNT是一个聚合函数,这就是它的工作方式。你得到每组的数量。

在第一个查询中,您要查询每个用户的userloginhistory数量。在第二个查询中,您要查询具有登录历史记录的用户数。

http://msdn.microsoft.com/en-us/library/ms173454.aspx