Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
T-SQL中的汉明权重/总体计数_Sql_Sql Server_Binary_Population_Hammingweight - Fatal编程技术网

T-SQL中的汉明权重/总体计数

T-SQL中的汉明权重/总体计数,sql,sql-server,binary,population,hammingweight,Sql,Sql Server,Binary,Population,Hammingweight,我正在寻找一种快速的方法来计算二进制(1024)字段的汉明权重/总体计数/“1位数”。MySQL有一个BIT_COUNT函数,可以实现类似的功能。我在t-SQL中找不到类似的函数 或者您会建议将二进制数据存储在另一种类型的字段中吗 如果你不知道我在说什么,这里有一个。没有找到任何关于汉明重量的特别信息,但这里有一个关于汉明距离的信息: create function HamDist(@value1 char(8000), @value2 char(8000)) returns int as be

我正在寻找一种快速的方法来计算二进制(1024)字段的汉明权重/总体计数/“1位数”。MySQL有一个BIT_COUNT函数,可以实现类似的功能。我在t-SQL中找不到类似的函数

或者您会建议将二进制数据存储在另一种类型的字段中吗


如果你不知道我在说什么,这里有一个。

没有找到任何关于汉明重量的特别信息,但这里有一个关于汉明距离的信息:

create function HamDist(@value1 char(8000), @value2 char(8000))
returns int
as
begin
    declare @distance int
    declare @i int
    declare @len int

    select @distance = 0,
           @i =1,
           @len = case when len(@value1) > len(@value2)
                       then len(@value1)
                       else len(@value2) end

    if (@value1 is null) or (@value2 is null)
        return null

    while (@i <= @len)
        select @distance = @distance +
                           case when substring(@value1,@i,1) != substring(@value2,@i,1)
                                then 1
                                else 0 end,
               @i = @i +1

    return @distance
end
创建函数HamDist(@value1字符(8000),@value2字符(8000))
返回整数
作为
开始
声明@distance int
声明@i int
声明@lenint
选择@distance=0,
@i=1,
@len=len(@value1)>len(@value2)时的情况
然后len(@value1)
else len(@value2)结束
如果(@value1为空)或(@value2为空)
返回空

虽然(@i我找不到一个好办法。最后,我用Java计算了汉明权重,并定期更新数据库中的位计数。

你可以使用一个辅助表,对小数字(如字节)使用预先计算好的汉明权重,然后相应地拆分值,加入到辅助表中,得到部分汉明权重的总和ghts作为值的汉明权重:

-- define Hamming weight helper table
DECLARE @hwtally TABLE (byte tinyint, hw int);
INSERT INTO @hwtally (byte, hw) VALUES (0, 0);
INSERT INTO @hwtally (byte, hw) SELECT   1 - byte, 1 - hw FROM @hwtally;
INSERT INTO @hwtally (byte, hw) SELECT   3 - byte, 2 - hw FROM @hwtally;
INSERT INTO @hwtally (byte, hw) SELECT   7 - byte, 3 - hw FROM @hwtally;
INSERT INTO @hwtally (byte, hw) SELECT  15 - byte, 4 - hw FROM @hwtally;
INSERT INTO @hwtally (byte, hw) SELECT  31 - byte, 5 - hw FROM @hwtally;
INSERT INTO @hwtally (byte, hw) SELECT  63 - byte, 6 - hw FROM @hwtally;
INSERT INTO @hwtally (byte, hw) SELECT 127 - byte, 7 - hw FROM @hwtally;
INSERT INTO @hwtally (byte, hw) SELECT 255 - byte, 8 - hw FROM @hwtally;

-- calculate
WITH split AS (
  SELECT SUBSTRING(@value, number, 1) AS byte
  FROM master.dbo.spt_values
  WHERE type = 'P' AND number BETWEEN 1 AND LEN(@value)
)
SELECT
  Value = @value,
  HammingWeight = SUM(t.hw)
FROM split s
  INNER JOIN @hwtally t ON s.byte = t.byte

当您使用较小的值(比如16位最大值)时,使用SQL Server最有效的方法是使用一个包含所有计算结果的表并使用联接

我已经将一个查询从30秒加速到0秒,通过对一个查询执行这种操作,该查询应该计算17000行上4位值的汉明权重

WITH HammingWeightHelper AS (
        SELECT  x, Fx 
        FROM (VALUES(0,0),(1,1),(2,1),(3,2),
                    (4,1),(5,2),(6,2),(7,3),
                    (8,1),(9,2),(10,2),(11,3),
                    (12,2),(13,3),(14,3),(15,4)) AS HammingWeight(x, Fx)
    )
SELECT HammingWeight.Fx As HammingWeight, SomeTable.Value As bitField
FROM   SomeTable INNER JOIN
       HammingWeightHelper ON HammingWeightHelper.x = SomeTable.Value 

当然,这是一个丑陋的解决方案,可能不适合长位字段。

这可能是CLR函数的工作。此外,您可能已经考虑过这一点,但如果唯一二进制值的计数是数千而不是数百万,则可以创建一个表来存储第一次计算后每个值的pop。或者存储它在你的主表中,因为你只需要一个
SMALLINT
。谢谢你的回复。它的算法与@Lamak已经发布的算法相同。但是实现速度不是很快。我必须先将字段转换为字符(类似于)然后调用这个例程。难道没有至少按字节计算汉明距离的方法吗?太好了!谢谢。以前不知道spt_值。@Simon:这里有一些有用的信息作为开始: