您将其与integer
变量进行比较的事实是无关紧要的。
的计划COUNT
始终有一个CONVERT_IMPLICIT(int,[ExprNNNN],0))
位置ExprNNNN
,该位置表示表示的结果的表达式的标签COUNT
。
我一直以为,最终用于的代码COUNT
将调用与相同的代码,COUNT_BIG
并且必须进行强制转换才能将其bigint
结果转换回int
。
实际上COUNT_BIG(*)
,在查询计划中甚至没有区别COUNT(*)
。两者都显示为Scalar Operator(Count(*))
。
COUNT_BIG(nullable_column)
确实在执行计划中与有所区别,但是执行计划COUNT(nullable_column)
仍然隐式转换到int
。
下面是这种情况的一些证据。
WITH
E1(N) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
) -- 1*10^1 or 10 rows
, E2(N) AS (SELECT 1 FROM E1 a, E1 b) -- 1*10^2 or 100 rows
, E4(N) AS (SELECT 1 FROM E2 a, E2 b) -- 1*10^4 or 10,000 rows
, E8(N) AS (SELECT 1 FROM E4 a, E4 b) -- 1*10^8 or 100,000,000 rows
, E16(N) AS (SELECT 1 FROM E8 a, E8 b) -- 1*10^16 or 10,000,000,000,000,000 rows
, T(N) AS (SELECT TOP (2150000000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS N FROM E16)
SELECT COUNT(CASE WHEN N < 2150000000 THEN 1 END)
FROM T
OPTION (MAXDOP 1)
在我的桌面上运行大约需要7分钟,并返回以下内容
消息8115,第16级,州2,第1行
将表达式转换为数据类型int的算术溢出错误。
警告:通过合计或其他SET操作消除了空值。
这表示COUNT
必须在a int
溢出(在2147483647)并且COUNT
操作员处理了最后一行(2150000000)之后导致必须NULL
返回的消息之后,必须继续执行操作。
通过比较将COUNT
表达式替换为SUM(CASE WHEN N < 2150000000 THEN 1 END)
return
消息8115,第16级,州2,第1行
将表达式转换为数据类型int的算术溢出错误。
没有ANSI
关于的警告NULL
。从中可以得出结论,在这种情况下,溢出发生在聚合本身之前,直到达到第2150,000,000行。
ScalarOperator
SSMS属性窗口中显示的值。