使用SQL Server 2008和TSQL的任何可用功能,我试图找出如何针对以下问题存在不涉及临时表的基于集合的解决方案:
给定一组具有父子关系的节点,以及一组适用于每个节点的键值对,并给出 在节点层次结构的更深层次上的值(对于给定的键值对)将覆盖具有相同键的值 继承自祖先节点,选择:
架构如下:
create table Node
(
ID bigint identity primary key,
ParentID bigint null foreign key references Node(ID),
Name nvarchar(100)
);
create table KeyValuePair
(
ID bigint identity primary key,
KeyName nvarchar(100) not null,
Value nvarchar(1000) not null,
NodeID bigint not null foreign key references Node(ID),
unique (KeyName, NodeID)
);
结果集基本上包括KeyName
,Value
,InheritedValue
列。
我一直在尝试使用公共表表达式来执行此操作,但它的逻辑有点棘手。
答案 0 :(得分:3)
我根据问题设置了Node和KeyValuePair表,并填充了一些示例值,以便我的层次结构如下:
根
| ---一个
| | --- A1
| | --- A2
|
| ---乙
| --- B1
| --- B2
我分配了两个名为“Property 1”和“Property 2”的属性,每个属性在root中定义,分别为“Root Prop 1”和“Root Prop 2”。在A中,我用值“A Prop 1”覆盖“Property 1”,在B中,我用值“B Prop 2”覆盖“Property 2”。
set identity_insert Node on
insert into Node(ID,ParentID,Name)
values (1,null,'Root'),(2,1,'A'),(3,1,'B'),(4,2,'A1'),(5,2,'A2'),
(6,3,'B1'),(7,3,'B2')
set identity_insert Node off
insert into KeyValuePair(KeyName, [Value], NodeID)
values ('Property 1','Root Prop 1',1),
('Property 2','Root Prop 2',1),
('Property 1','A Prop 1',2),
('Property 2','B Prop 2',3)
调用Nathan的节点A1解决方案不会产生任何行!
Nathan解决方案中的where子句应该是keys和v之间连接的条件,导致下面显示的修改过程(我也将DataValue重命名为KeyValuePair以与原始问题保持一致):
create procedure dbo.ListDataValues
@nodeid bigint
as
begin
with nodes as (
select ID, ParentID, 0 as Level
from Node n where ID=@nodeid
union all
select n.ID, n.ParentID, c.Level+1 as Level
from Node n inner join nodes c on c.ParentID = n.ID
),
keys as (
select distinct(KeyName)
from KeyValuePair
where NodeID in (select ID from nodes)
)
select
keys.KeyName,
v.Value,
i.Value as [InheritedValue],
i.NodeID as [InheritedFromNodeID]
from
keys
left join KeyValuePair v on v.KeyName = keys.KeyName
and v.NodeID = @nodeid
left join KeyValuePair i on i.KeyName = keys.KeyName
and i.NodeID = (select top 1 NodeID from KeyValuePair d
inner join nodes k on k.ID = d.NodeID
where Level > 0 and d.KeyName = i.KeyName
order by [Level])
end
go
这产生了预期的正确结果:
KeyName Value InheritedValue InheritedFromNodeID
------------ ------- ----------------- --------------------
Property 1 NULL A Prop 1 2
Property 2 NULL Root Prop 2 1
答案 1 :(得分:2)
您应该考虑使用嵌套集模型来存储层次结构。这是一个描述它的链接: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
它支持更友好的SQL方法来检索有关分层信息的常见信息。
然后,您可以通过Node上的查询和KeyValuePair的单个连接来满足您的要求。
答案 2 :(得分:0)
好的,我自己解决了。可能还有其他方法可以做到,但这似乎运作得很好:
create procedure dbo.ListDataValues
@nodeid bigint
as
begin
with nodes as (
select ID, ParentID, 0 as Level
from Node n where ID=@nodeid
union all
select n.ID, n.ParentID, c.Level+1 as Level
from Node n inner join nodes c on c.ParentID = n.ID
),
keys as (
select distinct(KeyName)
from DataValue
where NodeID in (select ID from nodes)
)
select v.KeyName, v.Value, i.Value as [InheritedValue], i.NodeID as [InheritedFromNodeID]
from keys
left join DataValue v on v.KeyName = keys.KeyName
left join DataValue i on i.KeyName = keys.KeyName
and i.NodeID = (select top 1 NodeID from DataValue d
inner join nodes k on k.ID = d.NodeID
where Level > 0 and d.KeyName = i.KeyName
order by Level)
where v.NodeID = @nodeid
end
答案 3 :(得分:0)
这是物化路径闪耀的情况之一。以下是我使用它解决类似问题的方法:
Store your configuration settings as a hierarchy in a database.