左连接返回计数为1,即使该计数不存在任何行?

时间:2016-04-26 21:13:09

标签: sql sql-server tsql

我的查询如下所示。它使用cte

SELECT  d.hour, 
        hourkey, 
        range, 
        COUNT(*) as 'count'
FROM dimhour d 
    LEFT JOIN cte2 
        ON d.hour = cte2.hourkey
        AND range IS NOT NULL
WHERE d.hour <= 23
GROUP BY d.hour, 
         hourkey, 
         range                
ORDER BY d.hour DESC

这是此查询的结果:

hour   hourkey  range    count
18     NULL     NULL     1
17     NULL     NULL     1
16     NULL     NULL     1
15     15       99%      15
14     14       99%      15
13     13       99%      15
12     12       99%      15
11     11       99%      15
10     10       99%      15

cte2的结果太大,无法在此发布,但我可以告诉您,cte2.hourkey null的小时数cte2内没有一行。在Hr15之后没有什么可以为count(*)返回正数。但count(*)以某种方式返回1。

为什么此查询在不存在的小时内返回count(*)为1,如何删除它们?

3 个答案:

答案 0 :(得分:3)

COUNT(*)将返回特定组中所有行的计数,包括它所在的行。如果您希望它计算特定列,则需要指定列,例如COUNT(cte2.hourkey)。这将计算组内的非空记录。

SELECT d.hour, hourkey, range, COUNT(cte2.hourkey) AS [count]
FROM dimhour d LEFT JOIN cte2 ON
d.hour = cte2.hourkey
AND range IS NOT NULL
WHERE d.hour <= 23
GROUP BY d.hour, hourkey, range                
ORDER BY d.hour desc

如果您根本不想显示行,则需要INNER JOIN而不是LEFT JOIN

SELECT d.hour, hourkey, range, COUNT(cte2.hourkey) AS [count]
FROM dimhour d INNER JOIN cte2 ON
d.hour = cte2.hourkey
AND range IS NOT NULL
WHERE d.hour <= 23
GROUP BY d.hour, hourkey, range                
ORDER BY d.hour desc

答案 1 :(得分:1)

表达式:

count(*) as [count]

返回结果集中的行数。 LEFT JOIN保证至少有一行,即使它不匹配。

要计算匹配项,请计算用于JOIN(或主键)的其中一列:

count(cte2.hourkey) as [count]

注意:仅对字符串和日期常量使用单引号。将它们用于色谱柱可能会在将来引发问题。

答案 2 :(得分:0)

从不同的角度回答,我认为可能更容易理解:

如果你拿出GROUP BY,你会得到:

hour   hourkey  range
18     NULL     NULL
17     NULL     NULL
16     NULL     NULL
15     15       99%
15     15       99%
15     15       99%
15     15       99%
15     15       99%
15     15       99%
15     15       99%
15     15       99%
15     15       99%
15     15       99%
15     15       99%
15     15       99%
15     15       99%
15     15       99%
15     15       99%
14     14       99%
...

如果您现在按hourhourkeyrange进行分组,您会看到18NULLNULL的行数?我发现了一排。它位于顶部。这就是COUNT(*)正在返回的内容。

这就是如何处理这个问题:你想要的数量是你可以从这个结果集中轻松获得的数量吗?如果没有,那么寻找另一种方法。在您的情况下,您似乎想要在cte2上进行分组。所以写下来吧!

select d.hour, sub.hourkey, sub.range, sub."count"
from dimhour d
left join (
    select cte2.hourkey, cte2.range, count(*) as "count"
    from cte2
    where cte2.range is not null
    group by cte2.hourkey, cte2.range
) as sub
on d.hour = sub.hourkey
where d.hour <= 23
order by d.hour desc

一个区别是,现在而不是0,您将获得NULL,但如果它困扰您,您可以使用ISNULL(sub."count", 0)来避免这种情况。