【问题标题】:What conditions cause CHECKSUM_AGG to return 0?什么条件导致 CHECKSUM_AGG 返回 0?
【发布时间】:2012-08-13 05:33:21
【问题描述】:

似乎有许多条件会导致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_AGG 调用中的CHECKSUM 值没有一个重复。

我希望任何描述导致 CHECKSUM_AGG 返回 0 的原因的答案也能解释这些情况。

【问题讨论】:

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


    【解决方案1】:

    例如,如果行数为偶数,或者值总和为特定值(例如 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
    

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

    【讨论】:

    • CHECKSUM for INT 只返回不变的相同值。这解释了为什么您会注意到一个包含少量小整数的模式:它们只是按原样异或。
    • @usr 对,我认为这是 Michael 的示例使用 FLOAT 而不是 INT 的部分原因(无论您有 20 行还是 200,000 行,结果都是一样的)。
    • 我只是举了我的例子,并对它们中的每一个进行了 XOR 技术,并且在每种情况下都得到了 0。这既可以回答它,也可以处理我的场景。谢谢!
    猜你喜欢
    • 2014-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-17
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    相关资源
    最近更新 更多