29

次の表があるとします。

CREATE TABLE BitValues ( n int )

サブクエリ内のnすべての行のビットごとのORを計算することは可能ですか?たとえば、BitValuesに次の4つの行が含まれている場合:

+ --- +
| n |
+ --- +
| 1 |
| 2 |
| 4 |
| 3 |
+ --- +

サブクエリが7を返すことを期待します。UDFを作成せずにこれをインラインで実行する方法はありますか?

4

10 に答える 10

13
WITH    Bits
          AS ( SELECT   1 AS BitMask
               UNION ALL
               SELECT   2
               UNION ALL
               SELECT   4
               UNION ALL
               SELECT   8
               UNION ALL
               SELECT   16
             )
    SELECT  SUM(DISTINCT BitMask)
    FROM    ( SELECT    1 AS n
              UNION ALL
              SELECT    2
              UNION ALL
              SELECT    3
              UNION ALL
              SELECT    4
              UNION ALL
              SELECT    5
              UNION ALL
              SELECT    6
            ) AS t
            JOIN Bits ON t.n & Bits.BitMask > 0
于 2010-10-20T19:02:32.997 に答える
12

この投稿はかなり古く、いくつかの有用な答えがありますが、これはかなりクレイジーで簡単な方法です...

Select  
    SUM(DISTINCT(n & 0x01)) +
    SUM(DISTINCT(n & 0x02)) +
    SUM(DISTINCT(n & 0x04))
    as OrN
From BitValues
于 2016-03-07T20:21:41.090 に答える
9

@AlexKuznetsovのソリューションと@Andomarのソリューションを組み合わせた単純なソリューション。
ビットマスクは再帰共通テーブル式によって生成されますが、@Andomarのソリューションよりも簡単な方法で生成されます。
次に、@AlexKuznetsovのソリューションと同じようにビットが合計されます。
この例では、16ビットのマスクが必要であると想定しているため、65536の制限があります。65536を2^Nに変更することにより、Nビットマスクを示すことができます。

WITH Bits AS
(
    SELECT 1 BitMask
    UNION ALL
    SELECT 2 * BitMask FROM Bits WHERE BitMask < 65536 -- recursion
)
SELECT SUM(DISTINCT BitMask)
FROM
    (SELECT 1 n
    UNION ALL
    SELECT 2 n
    UNION ALL
    SELECT 4 n
    UNION ALL
    SELECT 3 n) t
    INNER JOIN Bits ON t.n & Bits.BitMask > 0
于 2011-02-04T11:24:20.793 に答える
3

準備:

if object_id(N'tempdb..#t', N'U') is not null drop table #t;
create table #t ( n int );
insert into #t values (1), (2), (4), (3);

解決:

select max(n & 8) + max(n & 4) + max(n & 2) + max(n & 1) from #t;
于 2013-07-18T14:06:29.210 に答える
2

|変数を使用して、各行に対して「ビット単位または」( )を実行できます。

declare @t table (n int)
insert @t select 1 union select 2 union select 4

declare @i int
set @i = 0

select  @i = @i | n
from    @t

select @i

これは印刷し7ます。selectでの変数の割り当ては、公式にはサポートされていないことに注意してください。

より厳密にはSQLの方法で、ビットごとに1行のテーブルを作成できます。32番目のビットは負の整数であるため、このテーブルには31行が含まれます。この例では、再帰CTEを使用してそのテーブルを作成します。

declare @t table (n int)
insert @t select 1 union select 2 union select 3

; with bits(nr, pow) as 
(
    select  1
    ,       1
    union all
    select  nr + 1
    ,       pow * 2
    from    bits
    where   nr <= 30
)
select  sum(b.pow)
from    bits b
where   exists
        (
        select  *
        from    @t t  
        where   b.pow & t.n > 0
        )

これは、ソーステーブルの任意のビットが設定されているビットを合計します。

于 2010-10-20T18:28:45.107 に答える
1

COALESCE関数を使用してみましたが、機能します。例:

DECLARE @nOrTotal INT

SELECT @nOrTotal = COALESCE(@nOrTotal, 0) | nValor 
    FROM (SELECT 1 nValor
              UNION 
          SELECT 2
              UNION 
          SELECT 2) t

SELECT @nOrTotal

>> Result: 3
于 2012-07-27T18:25:54.550 に答える
1

これは、WITHなしの代替手段です(hurrah !!!):

    select sum(distinct isnull(n & BitMask, 0)) as resultvalue
    from 
    (
          SELECT    1 AS n
          UNION ALL
          SELECT    2
          UNION ALL
          SELECT    4
          UNION ALL
          SELECT    3
    ) t
    INNER JOIN (SELECT 0 BitMask union all SELECT 1 union all SELECT 2 union all SELECT 4 union all SELECT 8 union all SELECT 16 union all SELECT 32 union all SELECT 64 union all SELECT 128 union all SELECT 256 union all SELECT 512 union all SELECT 1024 union all SELECT 2048 union all SELECT 4096 union all SELECT 8192 union all SELECT 16384 union all SELECT 32768 union all SELECT 65536) Bits -- = SELECT POWER(2, 16)
    ON n & BitMask = BitMask;

GroupByの例も考えてみましょう。

 -- Setup temp table to produce an example --
 create table #BitValues
 (
    id int identity(1,1)
    ,value int
    ,groupby varchar(10)
 )

 insert into #BitValues
 SELECT    1 AS value, 'apples'
          UNION ALL
          SELECT    2, 'apples'
          UNION ALL
          SELECT    4, 'apples'
          UNION ALL
          SELECT    3, 'apples'

 -- Bit operation: --
  select groupby, sum(distinct isnull(value & BitMask, 0)) as tempvalue
  from #BitValues
  INNER JOIN (SELECT 0 BitMask union all SELECT 1 union all SELECT 2 union all SELECT 4 union all SELECT 8 union all SELECT 16 union all SELECT 32 union all SELECT 64 union all SELECT 128 union all SELECT 256 union all SELECT 512 union all SELECT 1024 union all SELECT 2048 union all SELECT 4096 union all SELECT 8192 union all SELECT 16384 union all SELECT 32768 union all SELECT 65536) Bits -- = SELECT POWER(2, 16)
      ON value & BitMask = BitMask
  group by groupby

最初の例は、WITHよりも遅いことを意図しています。ただし、GroupByを他のデータと一緒に使用する場合、クエリはコスト的にほぼ同じです。

これを行う別の方法は

    select 
    groupby
      ,max(case when n & 1 = 1 then 1 else 0 end)
            +
        max(case when n  & 2 = 2 then 2 else 0 end)
            +
        max(case when n & 4 = 4 then 4 else 0 end)  
            +
        max(case when n & 8 = 8 then 8 else 0 end)
            +
        max(case when n & 16 = 16 then 16 else 0 end)
            +
        max(case when n & 32 = 32 then 32 else 0 end)
            +
        max(case when n & 64 = 64 then 64 else 0 end)
            +
        max(case when n & 128 = 128 then 128 else 0 end)
            +
        max(case when n & 256 = 256 then 256 else 0 end)
            +
        max(case when n & 512 = 512 then 512 else 0 end)
            +
        max(case when n & 1024 = 1024 then 1024 else 0 end)
            as NewDNC
    from #BitValues
    group by groupby;

コードの繰り返し、もう少し読みやすく、実行コストが似ているため、少し悪化します。

于 2016-03-04T17:12:13.290 に答える
0

このようなものをお探しですか?

編集:他のコメントで述べたように、この回答は、BitValuesテーブルに2の累乗しか含まれないという仮定に基づいていました。質問の行の間を読み、インラインサブクエリの使用を推測しようとしました。

declare @BitValues table (
    n int
)

declare @TestTable table (
    id int identity,
    name char(10),
    BitMappedColumn int
)

insert into @BitValues (n)
    select 1 union all select 2 union all select 4

insert into @TestTable
    (name, BitMappedColumn)
    select 'Joe', 5 union all select 'Bob', 8

select t.id, t.name, t.BitMappedColumn
    from @TestTable t
        inner join (select SUM(n) as BitMask from @BitValues) b
            on t.BitMappedColumn & b.BitMask <> 0
于 2010-10-20T18:33:33.927 に答える
0

私にとってはそれが最善の解決策です。

declare @res int
set @res=0    
SELECT  @res=@res|t.n
    FROM    ( SELECT    1 AS n
              UNION ALL
              SELECT    2
              UNION ALL
              SELECT    3
              UNION ALL
              SELECT    4
              UNION ALL
              SELECT    5
              UNION ALL
              SELECT    6
            ) AS t
于 2016-08-04T12:46:29.580 に答える
-1

読み取り可能で再利用可能なソリューションの最善の策は、ビット単位またはを実行するカスタムCLRAggregateを作成することです。このタイプの操作を作成するためのチュートリアルは、次の場所にあります: http: //msdn.microsoft.com/en-us/library/91e6taax (VS.80).aspx

于 2010-10-20T18:52:03.083 に答える