あいまいなタイトルで申し訳ありません。問題をどのように要約すればよいか、私には思いつきませんでした。階層テーブル (例: ID int, ParentID int
) があり、 のサブツリーを生成する必要がありID
ます。これは、再帰的な CTE を使用して簡単に実行できます。難しいのは、ノードごとに、一連の対応する値の実行中のビット単位の OR を計算し、その結果が親ノードの同じ値になるビット OR を計算する必要があることです。これは、すべてのノードが親のビットマスクを継承し、独自の追加ビットを設定できることを意味します。CTE のアンカー メンバーでこの値を計算するには、以前の質問OUTER APPLY
で述べた手法を使用します。残念ながら、CTE の再帰部分で同じように計算することはできません。これは、CTE の使用と集計が許可されていないためです。SUM
私がやりたいことをするためにこれを再構築する方法はありますか?
declare @ID int
set @ID = 1
;with _Bits_(RowNum, BitMask) as
(
select
1,
1
union all select
RowNum + 1,
BitMask * 2
from
_bits_
where
RowNum < 31
),
_Tree_ as
(
select
a.ID,
a.ParentID,
b.BitMask
from
Tree a
outer apply
(
select
sum(distinct y.BitMask) as BitMask
from
BitValues x
inner join _Bits_ y
on (x.Value & y.BitMask) <> 0
where
x.ID = a.ID
) b
where
a.ID = @ID
union all select
a.ID,
a.ParentID,
c.BitMask | b.BitMask
from
Tree a
inner join _Tree_ b
on b.ID = a.ParentID
outer apply
(
select
sum(distinct y.BitMask) as BitMask
from
BitValues x
inner join _Bits_ y
on (x.Value & y.BitMask) <> 0
where
x.ID = a.ID
) c
)
select * from _Tree_
編集
問題を概念化するのに役立つ場合: 階層はディレクトリ構造によく似ており、ビットマスクは親フォルダーから継承されるアクセス許可に似ています。
サンプルデータ
create table Tree (ID int primary key, ParentID int null foreign key references Tree (ID))
insert Tree values (1, null)
insert Tree values (2, 1)
insert Tree values (3, 1)
create table BitValues (ID int not null foreign key references Tree (ID), BitMask int not null)
insert BitValues values (1, 1)
insert BitValues values (2, 2)
insert BitValues values (2, 4)
insert BitValues values (3, 8)
insert BitValues values (3, 16)
insert BitValues values (3, 32)
1 の場合@ID
、クエリは次のように返されると思います。
+----+----------+---------+ | | ID | 親 ID | ビットマスク | +----+----------+---------+ | | 1 | ヌル | 1 | | | 2 | 1 | 7 | | | 3 | 1 | 57 | +----+----------+---------+