所有可能的位组合

时间:2016-06-07 13:51:23

标签: sql sql-server sql-server-2008

假设我有一张桌子:

id      val
 0       1
 1       2
 2       4

我正在寻找可以返回val列的所有按位组合的SQL。举个例子,从上表中我可以看到以下可能的val组合:

1  -- from original table id: 0
2  -- from original table id: 1
3  -- combination of id: 0 & 1
4  -- from original table id: 2
5  -- combination of id: 0 & 2
6  -- combination of id: 1 & 2
7  -- combination of id: 0 & 1 & 2

2 个答案:

答案 0 :(得分:4)

此查询只返回sum(val)的所有组合,可能不是您要查找的内容。如果你正在寻找按位&你应该使用t.val & cur.val(感谢@Andrew Deighton) (我没有创建t表,而是我动态构建它。你不需要那个)

with t as
    (select 0 as id, 1 as val union all
     select 1 as id, 2 as val union all
     select 2 as id, 4 as val ),
 cur as 
    ( select id, val  from t union all
      select t.id, t.val + cur.val from cur join t on cur.id>t.id)
 select val
  from cur
order by val

<强>输出

val
1
2
3
4
5
6
7

如果添加val = 8的新记录,您将获得:

val
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

答案 1 :(得分:0)

你的桌子名为aTable - 我想出了这个

CREATE TABLE #combo (z bigint);

DECLARE @CNT integer;

SELECT @CNT = COUNT(0) FROM aTable;

DECLARE @I int;
SET @I = 0
WHILE @I < POWER(2, @CNT)
BEGIN
    INSERT #combo VALUES(@I);
    SET @I = @I + 1;
END

--select * from #combo;

;with cte as (select *, row_number() over (order by id) as rn from aTable),
    combs as (select c1.z,cte.rn, cte.val,  POWER(2, cte.rn -1) & c1.z as flag  from cte join #combo c1 ON POWER(2, cte.rn -1) & c1.z != 0 )


select *, row_number() over (partition by z order by rn) as lev, val final_val into #perms from combs  order by z,rn;

--select * from #perms;

DECLARE @depth as integer;
SET @depth = 2;



WHILE EXISTS (SELECT 0 FROM #perms WHERE lev = @depth)
begin

    UPDATE #perms 
    SET #perms.final_val = p.final_val & #perms.val
FROM
  #perms
INNER JOIN
  #perms p
ON
  p.lev = #perms.lev - 1 AND p.z = #perms.z 

  set @depth = @depth + 1;

end

select #perms.z,#perms.final_val from #perms join (SELECT p.z, max(p.lev) maxz FROM #perms p GROUP BY z) DQ ON #perms.lev = dq.maxz and dq.z = #perms.z order by #perms.z;

DROP TABLE #combo;
DROP TABLE #perms;

甚至

with t as
    (select * from atable),
 cur as 
    ( select id, val  from t union all
      select t.id, t.val & cur.val from cur join t on cur.id>t.id)
 select id,val
  from cur
order by id