1

似乎有许多条件会导致CHECKSUM_AGG返回 0,这是我没有预料到的。我只能找到一个讨论过的问题,即重复值会导致它。这可以通过 aDISTINCT或来解决GROUP 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 的原因的答案也能解释这些情况。

4

1 回答 1

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官方记录为不可靠,即它可能无法准确反映数据更改,对吗?该文档没有对此进行详细说明,它只是指出有时即使有变化,它也不会告诉您发生了变化。(实际措辞是“但是,校验和不会改变的可能性很小。”)

无论如何,迈克尔斯沃特似乎已经发现这CHECKSUM_AGG只是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

正如他继续解释的那样,当值的范围非常小时,这可能会导致误导性结果,因为生成可靠校验和的几率会迅速降低。

于 2012-08-16T20:15:20.163 回答