注意:我稍作编辑以反映您提供的示例数据。
设置
这是我必须代表您的嵌套集的内容:
declare @nestedSet table (
id int,
parentId int
);
insert @nestedSet values
(1, null), (2, 1), (4, 2), (7, 4), (8, 4), (10, 1), (9, 10), (1004, 1),
(3, null), (5, 3), (6, 3),
(13, null), (11, 13), (12, 13);
以下是我为您的促销活动构建的内容:
declare @promotions table (
promotionId int identity(1,1),
categoryId int,
price float
);
insert @promotions values (1, 5), (2, 15), (3, 10);
还有您的产品,我已将其重命名为 ProductCategories 以更好地反映其内容:
declare @productCategories table (productId int, categoryId int);
insert @productCategories values (1,7),(1,8),(1,6);
解决方案
作为主播,我只是拉入了产品表。但我认为在您的用例中,您需要一个过滤器来挑选合适的基础产品。然后我做了一个计算来检查该类别是否已经是促销活动。如果是,那么它代表一个叶节点。
在递归中,我只是将每个不是叶子的节点的嵌套集的层次结构向上移动。我再次计算一下该类别是否是促销,看看它是否是叶子节点。
从结果中,我选择了所有叶节点,按价格排序,并输出最上面的一个。
declare @productId int = 1;
with
traverse as (
select categoryId,
parentId,
isLeaf = iif(exists (
select 0
from @promotions pm
where pd.categoryId = pm.categoryId
), 1, 0)
from @productCategories pd
join @nestedSet n on pd.categoryId = n.id
where pd.productId = @productId
union all
select categoryId = par.id,
par.parentId,
isLeaf = iif(exists (
select 0
from @promotions pm
where par.id = pm.categoryId
), 1, 0)
from traverse pd
join @nestedSet par on pd.parentId = par.id
where pd.isLeaf = 0
)
select
top 1 p.*
from traverse t
join @promotions p on t.categoryId = p.categoryId
where isLeaf = 1
order by p.price