给定 SQL Server 2008 R2 中的int
列,用于保存十进制“编码”位标志(范围从2 0 到2 30 ,因此有31个可用标志,最大值为1073741824
)。该列可以包括整个可分配整数组合范围,所有这些都是对单个对象进行分类。
从有限数量的十进制“位整数”中,我们必须找到一个代表所有这些标志的某种交集的数字 -
就像你有3,10,524290
时一样,很明显应该在结果中设置2
,而其他位(1,8,524288
)是有争议的。这是一个非常基本的例子。这可能是一组真实的输入数据(仅限前两列):
Occurences | Decimal bit field | Binary representation 7 | 268435460 | 10000000000000000000000000100 5 | 268435488 | 10000000000000000000000100000 5 | 128 | 00000000000000000000010000000 4 | 32 | 00000000000000000000000100000 3 | 4 | 00000000000000000000000000100 3 | 268435492 | 10000000000000000000000100100 2 | 36 | 00000000000000000000000100100 2 | 132 | 00000000000000000000010000100 1 | 160 | 00000000000000000000010100000 Occurences of particular bit: 3--------------------3-6--6-- Desired output possibility: 10000000000000000000000100100
...在Transact-SQL中实现:
&-AND
)并将最大值除以2(>=1
时)。现在我为比特集输出了二进制代表。我考虑将这些位保存到31列临时表中以进行评估。但后来我开始思考:难道没有更聪明的方法吗? SQL Server速度超快,即使在反汇编10000个生成的整数时也是如此。但也许有一个内置函数来计算两个二进制位标志之间的“距离”。
我承认这是一个复杂的问题,但我真的做看到隧道尽头的灯光,即使它需要以间接的方式完成。它会变得更复杂,因为加权也应该在以后应用,因此2׬00010000
@ 100%显着性> 4×00010000
@ 40 %重要性。但是,当我生成一个摘要并且可用
答案 0 :(得分: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