2

BINARY(1024) フィールドのハミング重み/人口カウント/「1 ビットの数」を計算する高速な方法を探しています。MySQL には、そのようなことを行う BIT_COUNT 関数があります。T-SQL で同様の関数を見つけることができませんでしたか?

または、バイナリ データを別のタイプのフィールドに格納することをお勧めしますか?

何を言っているのかわからない場合は、ハミングの重みに関するウィキペディアの記事をご覧ください。

4

4 に答える 4

5

バイトなどの小さな数値に対して事前に計算されたハミング重みを持つヘルパー テーブルを使用し、それに応じて値を分割し、ヘルパー テーブルに結合して、部分的なハミング重みの合計を値のハミング重みとして取得できます。

-- 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
于 2011-05-08T22:58:48.497 に答える
2

小さい値 (最大 16 ビットなど) で遊んでいる場合、SQL Server でそれを行う最も効率的な方法は、すべての結果が計算されたテーブルを使用し、結合を使用することです。

17'000 行で 4 ビット値のハミング重みを計算する必要があるクエリでこの種のことを行うことにより、クエリを 30 秒から 0 秒に高速化しました。

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 

もちろん、これは醜い解決策であり、おそらく長いビット フィールドには適していません。

于 2015-10-13T14:33:32.427 に答える
0

いい方法が思いつきませんでした。最後に、Java でハミングの重みを計算し、データベースのビット数を定期的に更新しました。

于 2011-05-08T21:37:43.073 に答える
0

ハミングの重みについては特に何も見つかりませんでしたが、ハミングの距離については次のとおりです。

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

これは、2 つの値の間のハミング距離を計算します。単一の値のハミング重みは、その値とゼロ値の配列の間のハミング距離になります。

于 2011-05-06T20:09:17.547 に答える