この混乱により、サンプルデータからサンプル結果が生成されます。 あなたが何であるかはまだはっきりしていません アルゴリズムはあるべきだと思います。
declare @CategoryItems as Table (
CategoryName NVarChar(255),
Label NVarChar(255),
ProductId Int,
ChildCategoryId Int,
CategoryId Int );
declare @Categories as Table (
CategoryId Int,
Name NVarChar(100) );
insert into @CategoryItems ( CategoryName, Label, ProductId, ChildCategoryId, CategoryId ) values
( 'CategoryA', 'Widget A', 1, 0, 1 ),
( 'CategoryB', 'CategoryA', 0, 1, 2 ),
( 'CategoryC', 'Widget B', 2, 0, 3 );
insert into @Categories ( CategoryId, Name ) values
( 1, 'CategoryA' ),
( 2, 'CategoryB' ),
( 3, 'CategoryC' );
select * from @Categories;
select * from @CategoryItems;
declare @TargetProductId as Int = 1;
with Leonard as (
-- Start with the target product.
select 1 as [Row], ProductId, Label, CategoryId, ChildCategoryId
from @CategoryItems
where ProductId = @TargetProductId
union all
-- Add each level of child category.
select L.Row + 1, NULL, CI.Label, CI.CategoryId, CI.ChildCategoryId
from @CategoryItems as CI inner join
Leonard as L on L.CategoryId = CI.ChildCategoryId ),
Gertrude as (
-- Take everything that makes sense.
select Row, ProductId, Label, CategoryId, ChildCategoryId
from Leonard
union
-- Then tack on an extra row for good measure.
select L.Row + 1, NULL, C.Name, NULL, C.CategoryId
from Leonard as L inner join
@Categories as C on C.CategoryId = L.CategoryId
where L.Row = ( select Max( Row ) from Leonard ) )
select Row, ProductId, Label, CategoryId, ChildCategoryId
from Gertrude
order by Row;
問題は、データが偏った形で混在していることだと思います。カテゴリの階層は通常、次のように表されます。
declare @Categories as Table (
CategoryId Int Identity,
Category NVarChar(128),
ParentCategoryId Int Null );
各階層のルートは、ParentCategoryId is NULL
で示されます。 。これにより、任意の数の独立したツリーを1つのテーブルに共存させることができ、製品の存在に依存しません。
商品が単一の(サブ)カテゴリに割り当てられている場合は、CategoryId
を含めるだけです。 Products
内 テーブル。製品が複数の(サブ)カテゴリに割り当てられている可能性がある場合は、おそらく異なる階層で、別のテーブルを使用してそれらを関連付けます。
declare @ProductCategories as Table (
ProductId Int,
CategoryId Int );