如果我问你能不能准确的从1数到10,相信你肯定认为我在开玩笑?
因为这如同问你是否读完了小学。
然而,读了下面的文章后,我相信,你可能要自己问自己,
我能不能从1数到10或者问我读完小学了吗?
先准备数据。
use tempdb;
DECLARE @T TABLE
( A INT IDENTITY PRIMARY KEY,
B VARCHAR(10) NULL
)
INSERT INTO @T(B)
SELECT 'A'
INSERT INTO @T(B)
SELECT 'B'
INSERT INTO @T(B)
SELECT 'C'
INSERT INTO @T(B)
SELECT NULL
INSERT INTO @T(B)
SELECT NULL
INSERT INTO @T(B)
SELECT 'D'
然后用我们最常用的COUNT(*)来查看记录数,
SELECT COUNT(*) count1 FROM @T
count1
-----------
6
(1 row(s) affected)
没错,返回6,是6条记录。我扳着手指头可以数清楚。
然而再看这条语句,你认为应该返回几呢?
6,5还是4。
如果你回答4,那么恭喜你答对了。
SELECT COUNT(B) count2 FROM @T
count2
-----------
4
Warning: Null value is eliminated by an aggregate or other SET operation.
(1 row(s) affected)
SQL Server给出了警告,告诉你空值(NULL)被聚合函数忽略掉了。
相应的下面的语句也不会返回2,而是0。
SELECT COUNT(B) count3 FROM @T
WHERE B IS NULL
count3
-----------
0
Warning: Null value is eliminated by an aggregate or other SET operation.
(1 row(s) affected)
如果你想知道B列为空值的行数,那么你可以将上面的语句改为
SELECT COUNT(*) count3 FROM @T
WHERE B IS NULL
或者
SELECT COUNT(1) count3 FROM @T
WHERE B IS NULL
下面的语句和count2中一样,空值被忽略,返回结果为4。
SELECT COUNT(DISTINCT B) count4 FROM @T
count4
-----------
4
Warning: Null value is eliminated by an aggregate or other SET operation.
(1 row(s) affected)
同理,根据对空值列计算count空值行会被忽略,我们可以得知下面3条语句的返回结果应该是:
count5
-----------
5
count6
-----------
4
count7
-----------
5
SELECT COUNT(*) count5
FROM
(
SELECT DISTINCT B
FROM @T
) A
SELECT COUNT(B) count6
FROM
(
SELECT DISTINCT B
FROM @T
) A
SELECT COUNT(1) count7
FROM
(
SELECT DISTINCT B
FROM @T
) A
结论:
在对允许为空的列进行count求值时,要清楚你是否要将空值列计算在内,空值列只计算一次还是要多次计算。必要时可以考虑使用SUM(CASE WHEN COL IS NULL THEN 1 ELSE 0 END)来计算记录数。
例如:
SELECT
SUM(CASE WHEN B IS NULL THEN 1 ELSE 0 END) count8
FROM @T