2016-06-07 102 views
4

假設我有一個表:所有可能的比特組合

id  val 
0  1 
1  2 
2  4 

我找的SQL,將返回我val列是可能的所有的按位組合。因此,作爲一個例子,從上表中我希望以下可能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 
+0

你準備使用臨時表和遊標/存儲過程的程序邏輯?我假設你想要n條記錄,所以可能會有20條記錄(例如,它仍然有合理的記錄輸出數量!) – Cato

+3

在數據庫中進行位錯很少是一個好主意。如果您想要存儲多個事實,請存儲多行 - 不要將它們全部整理到一個列中。 –

回答

4

這個查詢僅返回總和(VAL)所有組合,您正在尋找可能沒有什麼。如果您正在尋找逐位&你應該使用t.val & cur.val(感謝@Andrew戴頓) (我沒有創建的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 
+0

不會執行任何按位操作,我可以看到雖然 – Cato

+0

不會執行它,但如果您使用&而不是+運算符? – Cato

+0

用叔如 (選擇0作爲ID,1作爲VAL UNION ALL 選擇1作爲ID,2爲VAL UNION ALL 選擇2爲ID,4爲VAL), CUR如 (選擇ID,VAL從噸工會所有 選擇t.id,t.val&cur.val從CUR加入噸上cur.id> t.id) 由VAL – Cato

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