我有两个相互链接的表。一个是一组值和一个可空的外键,它指向另一个表的Id,其中包含 2 外键返回到另一个表。
HierarchicalTable
Id LeftId RightId SomeValue
1 1 2 some value
2 3 4 top level in tree
3 5 6 incorrect hierarchy 1
4 7 8 incorrect result top level
IntermediateTable
Id SomeValue HierarchicalTableId
1 some value NULL
2 value NULL
3 NULL 1
4 value NULL
5 incorrect result 1 NULL
6 incorrect result 3 NULL
7 incorrect result 3 NULL
8 NULL 3
每个表都指向 down 层次结构。以下是针对分层表记录1& 2及其IntermediateTable值:
(H : HierarchicalTable, I : IntermediateTable)
H-2
/ \
I-3 I-4
/
H-1
/ \
I-1 I-2
我需要能够为给定的HierarchicalTable发送Id
并获取其下的所有HierarchicalTable记录。因此,对于上面的结构,如果我将1传递给查询,我应该得到H-1(从那里,我可以加载相关的IntermediateTable
值)。如果我通过2,我应该得到H-2和H-1(并再次使用它们来加载相关的IntermediateTable
值。)
我尝试过使用CTE,但有些主要内容与我见过的例子不同:
如果我运行此查询:
declare @TargetId bigint = 2
;
with test as (
select h.*
from dbo.hierarchicaltable h
inner join dbo.intermediatetable i
on (h.leftid = i.id or h.rightid = i.id)
union all
select h.*
from dbo.hierarchicaltable h
where h.id = @TargetId
)
select distinct *
from test
我在HierarchicalTable
中获得了所有4条记录,而不仅仅是记录1& 2.我不确定我想要的是否可以用CTE。
答案 0 :(得分:1)
试试这个: 我用两个表构建整个树,然后过滤(只有分层表记录)。
DECLARE @HierarchicalTable TABLE(
Id INT,
LeftId INT,
RightId INT,
SomeValue VARCHAR(MAX)
)
INSERT INTO @HierarchicalTable
VALUES
(1, 1, 2, 'some value '),
(2, 3, 4, 'top level in tree '),
(3, 5, 6, 'incorrect hierarchy 1 '),
(4, 7, 8, 'incorrect result top level')
DECLARE @IntermediateTable TABLE(
Id INT,
SomeValue VARCHAR(MAX),
HierarchicalTableId INT
)
INSERT INTO @IntermediateTable
VALUES
(1, 'some value' ,NULL ),
(2, 'value ' ,NULL ),
(3, NULL ,1 ),
(4, 'value ' ,NULL ),
(5, 'incorrect result 1' ,NULL ),
(6, 'incorrect result 3' ,NULL ),
(7, 'incorrect result 3' ,NULL ),
(8, NULL ,3 )
DECLARE @TargetId INT = 2;
WITH CTE AS (
SELECT Id AS ResultId, LeftId, RightId, NULL AS HierarchicalTableId
FROM @HierarchicalTable
WHERE Id = @TargetId
UNION ALL
SELECT C.Id AS ResultId, C.LeftId, C.RightId, NULL AS HierarchicalTableId
FROM @HierarchicalTable C
INNER JOIN CTE P ON P.HierarchicalTableId = C.Id
UNION ALL
SELECT NULL AS ResultId, NULL AS LeftId, NULL AS RightId, C.HierarchicalTableId
FROM @IntermediateTable C
INNER JOIN CTE P ON P.LeftId = C.Id OR P.RightId = C.Id
)
SELECT *
FROM CTE
WHERE ResultId IS NOT NULL