Nie ma znaczenia fakt, że porównujesz ją ze integerzmienną.
Plan COUNTzawsze ma CONVERT_IMPLICIT(int,[ExprNNNN],0))gdzie ExprNNNNjest etykieta dla wyrażenia reprezentującego wynik COUNT.
Zawsze zakładałem, że kod COUNTtylko wywołuje ten sam kod co COUNT_BIGi rzutowanie jest konieczne, aby przekonwertować bigintwynik tego z powrotem na int.
W rzeczywistości COUNT_BIG(*)nawet nie rozróżnia się w planie zapytań COUNT(*). Oba pojawiają się jako Scalar Operator(Count(*)).
COUNT_BIG(nullable_column)wyróżnia się w planie wykonania od, COUNT(nullable_column) ale ten drugi wciąż wraca do domyślnego rzutu int.
Niektóre dowody na to, że tak jest, znajdują się poniżej.
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)
Uruchomienie na moim pulpicie zajmuje około 7 minut i zwraca następujące
Msg 8115, poziom 16, stan 2, wiersz 1
Błąd przepełnienia arytmetycznego podczas konwersji wyrażenia na typ danych int.
Ostrzeżenie: Wartość zerowa jest eliminowana przez agregację lub inną operację SET.
Co wskazuje, że COUNTciąg dalszy musi nastąpić po intprzepełnieniu (w 2147483647), a ostatni wiersz (2150000000) został przetworzony przez COUNToperatora, co spowodowało wyświetlenie komunikatu o zwrocie NULL.
Dla porównania, zastępując COUNTwyrażenie SUM(CASE WHEN N < 2150000000 THEN 1 END)zwrotami
Msg 8115, poziom 16, stan 2, wiersz 1
Błąd przepełnienia arytmetycznego podczas konwersji wyrażenia na typ danych int.
bez ANSIostrzeżenia o NULL. Z tego wnioskuję, że przepełnienie nastąpiło w tym przypadku podczas samej agregacji przed osiągnięciem wiersza 2 150 000 000.
ScalarOperatorwartość pokazaną w oknie właściwości SSMS.