SQL按位比较一列中的不同组

时间:2014-03-22 23:19:34

标签: sql sql-server

我想获得下一个表的按位AND比较结果

  

gr
  1 300
  1 340
  1 150
  2 520
  2 460

在这个例子中,我希望看到300,340和150(组1)之间以及520和460(组2)之间的比较。 问题是每个组中的元素数量可以是任意数量。

2 个答案:

答案 0 :(得分:0)

你可以这样做你想做的事情:

select gr,
       (min(value & 1) + min(value & 2) + min(value & 4) + min(value & 8) + min(value & 16) +
        min(value & 32) + min(value & 64) + min(value & 128) + min(value & 256) & min(value & 512)
       ) as bit_and
from table t
group by gr;

您可能需要将汇总扩展为更高的位值。

答案 1 :(得分:0)

这里的例子(感谢Vyacheslav Davydenko):

-- example for aggregate bitwise operations
SET NOCOUNT ON

declare @t table (gr int, mask tinyint)

INSERT INTO @t(gr, mask) VALUES
 (1, 1) -- 00000001
,(1, 3) -- 00000011
,(1, 5) -- 00000101
,(2, 9) -- 00001001
,(2, 8) -- 00001000

select 'source',* from @t

declare @maskSize tinyint = 8*(select top 1 DataLength(mask) from @t) -- bits count

-- bitwise AND
;with Bits as
(
    select BitMask=cast(1 as bigint)
    union all
    select 2 * BitMask from Bits where BitMask < POWER(cast(2 as bigint), @maskSize)
)
, ResultBit AS
(
    select gr, res=sum(BitMask)
    from (
        select gr, BitMask, cnt=count(BitMask), sm=sum(res)
        from (
            select 
                t.gr
                ,b.BitMask
                ,res=iif(t.mask & b.BitMask=0, 0, 1)
            from @t t
            cross join Bits b
        )z
        group by gr, BitMask
        having count(BitMask)=sum(res)
    )z
    group by gr
)
select example='AND',* from ResultBit
order by gr

-- bitwise OR
;with Bits as
(
    select BitMask=cast(1 as bigint)
    union all
    select 2 * BitMask from Bits where BitMask < POWER(cast(2 as bigint), @maskSize)
)
, ResultBit AS
(
    select 
        gr
        ,res=SUM(DISTINCT iif(t.mask & b.BitMask=0, 0, b.BitMask)) -- 
    from @t t
    cross join Bits b
    group by gr
)
select example='OR',* from ResultBit

结果你得到:

;gr;mask
source;1;1
source;1;3
source;1;5
source;2;9
source;2;8

example;gr;res
AND;1;1
AND;2;8

example;gr;res
OR;1;7
OR;2;9