【问题标题】:SQL Bitwise comparison for different groups in one column一列中不同组的SQL按位比较
【发布时间】:2014-04-30 08:48:24
【问题描述】:

我想得到下一张表的按位与比较结果

gr 价值
1 300
1 340
1 150
2 520
2 460

在此示例中,我想查看 300、340 和 150(第 1 组)以及 520 和 460(第 2 组)之间的比较。 问题是每个组中的元素数量可以是任意的。

【问题讨论】:

  • 没有内置函数。您可能会觉得这很有启发性:stackoverflow.com/questions/3981050/….
  • 谢谢。我现在去看看
  • 我不明白在那个例子中为什么 AND 运算会给出 OR 的结果。据我了解,二进制中的 1、2、3 和 4 没有任何共同点,因此所有和的 AND 运算应该给出 0。但 OR 反而给出 111,即 12 月的 7。

标签: sql sql-server


【解决方案1】:

你可以用这种方式做你想做的事:

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;

您可能需要将总和扩展到更高的位值。

【讨论】:

    【解决方案2】:

    这是一个例子(感谢 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多