4

技術的な状況:

SQL Server 2008 R2には、10 進数で「エンコードされた」ビット フラグ (2 0から 2 30の範囲で、最大で 31 個のフラグが使用可能) を保存するためのint列があります。この列は、単一のオブジェクトを分類するために、割り当て可能な整数の組み合わせの全範囲を含む場合があります。1073741824

解決すべき問題:

有限個の 10 進数の「ビット整数」から、これらすべてのフラグの何らかの交点を表す単一の数値を見つける3,10,524290必要2があります1,8,524288。議論の余地があります。これは非常に基本的な例です。これは、入力データの実際のセットである可能性があります (最初の 2 列のみ)。

オカレンス | 10 進ビット フィールド | バイナリ表現
     7 | 268435460 | 1000000000000000000000000100
     5 | 268435488 | 10000000000000000000000100000
     5 | 128 | 00000000000000000000010000000
     4 | 32 | 00000000000000000000000100000
     3 | 4 | 0000000000000000000000000100
     3 | 268435492 | 10000000000000000000000100100
     2 | 36 | 00000000000000000000000100100
     2 | 132 | 00000000000000000000010000100
     1 | 160 | 00000000000000000000010100000
   特定のビットの出現: 3--------------------3-6--6--
     希望の出力可能性: 1000000000000000000000100100

これまでの解決策:

… Transact-SQL で実装:

  1. 評価するすべての整数を収集し、それらをコンマ区切りの文字列に連結します。
  2. 文字列を減らし、最初の数字を取り出し、ループします:
  3. testee を最大値 ( &-AND) と照合し、最大値を 2 で割る (while >=1)。

… これまでのところ?ó.Ò

これで、ビット セットのバイナリ表現の出力が得られました。これらのビットを 31 列の一時テーブルに保存して、評価を行うことを検討します。しかし、私は考えるようになりました:これを行うためのより賢い方法はありませんか? SQL Server は、生成された 10000 個の整数を逆アセンブルする場合でも超高速です。しかし、2 つのバイナリ ビット フラグ間の「距離」を計算するための組み込み関数があるかもしれません。

複雑な問題であることは認めますが、状況に応じた方法で実行する必要がある場合でも、トンネルの終わりに光が見えます. 000100002× ¬ @ 100% の有意性>00010000@ 40% の有意性となるように、重み付けも後で適用する必要があるため、さらに複雑になります。しかし、要約が生成されて利用可能になったら、これに対処しようとします;-)

4

1 に答える 1

1

ビット単位で操作に使用できます

declare @i int
declare @x int
declare @cnt int
select @i=2147483647  -- 1111111 11111111 11111111 11111111
declare @t table (a int)
insert into @t values( 3),(10),(524290);

Select @i= (@i & a) from @t 


-- just for fun an output
set @x=1
set @cnt=0
While @cnt<31
  begin
  Print Case when @x & @i <> 0 then 'X' else ' ' end  +' ' + Cast(@x as Varchar(12))   
  Set @cnt=@cnt + 1
  if @cnt<31  Set @x=@x*2
  end 

またはより良い出力で

declare @i int
declare @x int
declare @cnt int
select @i=2147483647  -- 1111111 11111111 11111111 11111111
Declare  @ref table(ref int) 
set @x=1
set @cnt=0
While @cnt<31
  begin
  insert into @ref Values(@x)
  Set @cnt=@cnt + 1
  if @cnt<31  Set @x=@x*2
  end 


declare @t table (a int)
insert into @t values( 3),(10),(524290);

Select @i= (@i & a) from @t 

Select * from @ref where ref&@i<>0 

あなたのコメントへの答えとして

declare @i int
declare @x int
declare @cnt int
select @i=2147483647  -- 1111111 11111111 11111111 11111111
Declare  @ref table(ref int) 
set @x=1
set @cnt=0
While @cnt<31
  begin
  insert into @ref Values(@x)
  Set @cnt=@cnt + 1
  if @cnt<31  Set @x=@x*2
  end 


declare @t table (a int)
insert into @t values( 3),(5),(9),(17),(33),(65),(128);

Select @i= (@i & a) from @t 

Select a,Count(*) as BitCount
from @ref r
join @t t on t.a & r.ref<>0
group by a

Select ref,Count(*) as OCC from @ref r
join @t t on t.a & r.ref<>0
group by ref

Select ref,(Select count(*) from @t where a & r.ref<>0) as OCC
from @ref r
于 2013-02-19T15:56:09.923 に答える