O fato de você estar comparando-o com uma integer
variável é irrelevante.
O plano para COUNT
sempre tem um CONVERT_IMPLICIT(int,[ExprNNNN],0))
onde ExprNNNN
é o rótulo da expressão que representa o resultado do COUNT
.
Minha suposição sempre foi que o código COUNT
acaba chamando o mesmo código COUNT_BIG
e o elenco é necessário para converter o bigint
resultado desse código novamente em int
.
De fato, COUNT_BIG(*)
nem sequer se distingue no plano de consulta COUNT(*)
. Ambos aparecem como Scalar Operator(Count(*))
.
COUNT_BIG(nullable_column)
se diferencia no plano de execução, COUNT(nullable_column)
mas o último ainda recebe uma conversão implícita de volta para int
.
Algumas evidências de que esse é o caso estão abaixo.
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)
Demora cerca de 7 minutos para ser executado na minha área de trabalho e retorna o seguinte
Msg 8115, nível 16, estado 2, linha 1
Erro de estouro aritmético ao converter expressão em tipo de dados int.
Aviso: O valor nulo é eliminado por uma operação agregada ou outra operação SET.
O que indica que o item COUNT
deve ter continuado após um int
transbordamento (em 2147483647) e a última linha (2150000000) foi processada pelo COUNT
operador, levando à mensagem sobre NULL
a devolução.
A título de comparação, substituindo a COUNT
expressão por SUM(CASE WHEN N < 2150000000 THEN 1 END)
retornos
Msg 8115, nível 16, estado 2, linha 1
Erro de estouro aritmético ao converter expressão em tipo de dados int.
sem ANSI
aviso sobre NULL
. A partir do qual concluo que o excesso ocorreu neste caso durante a agregação em si antes que a linha 2.150.000.000 fosse alcançada.
ScalarOperator
valor mostrado na janela de propriedades do SSMS.