什么条件导致CHECKSUM_AGG返回0?

时间:2012-08-16 19:50:06

标签: sql sql-server tsql sql-server-2008-r2 checksum

似乎有许多条件导致CHECKSUM_AGG返回0,这是我没想到的。我只能找到一个讨论过的,重复的值会导致它。这可以通过DISTINCTGROUP BY来解决。

我还发现了一些对我不太感兴趣的场景。一个是由我的老板提供的,一个是我找到的MSDN。这些我不知道如何解释。下面是一些演示场景的SQL:

SELECT
    CHECKSUM_AGG(T.Number) AS ChecksumAgggregate
FROM
(
    VALUES
        (2)
        , (3)
        , (4)
        , (5)
)AS T(Number)

DECLARE @t TABLE 
(
    Category VARCHAR(15),
    Value VARCHAR(10)
)

INSERT @t 
(
    Category
    , Value
)
VALUES 
    ('OneCharacter','a')
    ,('OneCharacter','b')
    ,('OneCharacter','c')
    ,('OneCharacter','d')

    ,('TwoCharacters','aa')
    ,('TwoCharacters','bb')
    ,('TwoCharacters','cc')
    ,('TwoCharacters','dd')

    ,('ThreeCharacters','aaa')
    ,('ThreeCharacters','bbb')
    ,('ThreeCharacters','ccc')
    ,('ThreeCharacters','ddd')

    ,('SixCharacters','aaaaaa')
    ,('SixCharacters','bbbbbb')
    ,('SixCharacters','cccccc')
    ,('SixCharacters','dddddd')

    ,('AllValues','a')
    ,('AllValues','b')
    ,('AllValues','c')
    ,('AllValues','d')
    ,('AllValues','aa')
    ,('AllValues','bb')
    ,('AllValues','cc')
    ,('AllValues','dd')
    ,('AllValues','aaa')
    ,('AllValues','bbb')
    ,('AllValues','ccc')
    ,('AllValues','ddd')
    ,('AllValues','aaaaaa')
    ,('AllValues','bbbbbb')
    ,('AllValues','cccccc')
    ,('AllValues','dddddd')

select 
    Category, CHECKSUM_AGG(CHECKSUM(Value)) 
from @t 
group by Category

select Category, Value, CHECKSUM(Value) ValueChecksum
from @t

来自这些查询的CHECKSUM_AGG的这些示例中只有0。最后一个查询显示,CHECKSUM调用中输入的CHECKSUM_AGG值都不重复。

我希望无论答案如何描述导致CHECKSUM_AGG返回0的原因,也会解释这些情况。

1 个答案:

答案 0 :(得分:3)

例如,如果存在偶数行,或者值总和到某些值(例如14),则会发生这种情况。这两个都产生0:

SELECT CHECKSUM_AGG(N)
FROM (VALUES (1),(2),(3),(4),(4)) AS T(N);

SELECT CHECKSUM_AGG(N)
FROM (VALUES (2),(3),(4),(5)) AS T(N);

但这些不是:

SELECT CHECKSUM_AGG(N)
FROM (VALUES (1),(2),(3),(4),(5)) AS T(N);

SELECT CHECKSUM_AGG(N)
FROM (VALUES (2),(3),(4),(6)) AS T(N);

14可能只是巧合(并且6行中的值不会发生),我之所以提到它只是因为它是我在这里注意到的唯一模式。我不知道任何这些案例都有记录。

您也知道CHECKSUM_AGG is officially documented as being not reliable,即它可能无法准确反映数据变化,对吧?该文档没有详细说明,它只是声明有时它不会告诉你即使有变化也会有变化。 (实际的措辞是“但是,校验和不会改变。”)

无论如何Michael Swart seems to have discovered that CHECKSUM_AGG is just XOR(这是他的证明):

CREATE TABLE #f(a FLOAT);
GO

INSERT #f VALUES (RAND());
GO 20

DECLARE @i INT = 0;
SELECT @i = @i ^ CHECKSUM(a) FROM #f;
SELECT @i, CHECKSUM_AGG(CHECKSUM(a)) FROM #f;
GO

DROP TABLE #f;
GO

当他继续解释时,当值的范围非常小时,这可能导致误导结果,因为产生可靠校验和的可能性迅速减少。