您将其与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行。
ScalarOperatorSSMS属性窗口中显示的值。