Roy*_*mir 16 t-sql sql-server common-table-expression sql-server-2008
我有一个包含层次结构数据的表 - 类似于:
childID | parentID
____________________
1 | 5
5 | 9
9 | 20
2 | 4
3 | 7
7 | 8
8 | 8
20 | 20
4 | 4
8 | 8
Run Code Online (Sandbox Code Playgroud)
期望的输出:

我创建了一个递归CTE,它找到了我的顶部fatherID.
就像是:
;WITH cte AS (
SELECT a.childID
,a.parentID
,1 AS lvl
FROM [Agent_Agents] a
WHERE a.childID = 214 //<==== value to begin with !! - thats part the problem
UNION ALL
SELECT tmp.childID
,tmp.parentID
,cte.lvl+1
FROM [Agent_Agents] tmp
INNER JOIN cte ON tmp.childID = cte.parentID
WHERE cte.childID<>cte.parentID
)
SELECT *
FROM cte
WHERE lvl = (
SELECT MAX(lvl)
FROM cte
)
Run Code Online (Sandbox Code Playgroud)
问题:
我以明确的 childID值执行了CTE 以(214)开始!所以它只给我214的价值.CTE执行递归部分并找到childID的topParent.
但
我想ForEach row in the Table- 用childID值来执行CTE !
我试过这样做CROSS APPLY:
就像是:
select * from myTable Cross Apply (
;WITH cte AS (....)
)
Run Code Online (Sandbox Code Playgroud)
但恕我直言(从我的测试!!) - 这是不可能的.
将递归CTE放入UDF的另一个想法是性能损失(我们知道udf的问题).
如何创建此查询以使其实际工作?(或一些接近解决方案)?
这是我尝试过的
https://data.stackexchange.com/stackoverflow/query/edit/69458
mar*_*c_s 21
你不能这样做吗?
;WITH cte AS (....)
SELECT
*
FROM
cte
CROSS APPLY
dbo.myTable tbl ON cte.XXX = tbl.XXX
Run Code Online (Sandbox Code Playgroud)
将CTE定义CROSS APPLY 之后的内容放入一个引用回CTE的SQL语句中.那会不会工作?
或者: - 绕过你的逻辑 - 做一个"自上而下"的CTE,首先选择顶级节点,然后遍历hiearchy.这样,您可以轻松确定递归CTE的第一部分中的"顶级父亲" - 如下所示:
;WITH ChildParent AS
(
SELECT
ID,
ParentID = ISNULL(ParentID, -1),
SomeName,
PLevel = 1, -- defines level, 1 = TOP, 2 = immediate child nodes etc.
TopLevelFather = ID -- define "top-level" parent node
FROM dbo.[Agent_Agents]
WHERE ParentID IS NULL
UNION ALL
SELECT
a.ID,
ParentID = ISNULL(a.ParentID, -1),
a.SomeName,
PLevel = cp.PLevel + 1,
cp.TopLevelFather -- keep selecting the same value for all child nodes
FROM dbo.[Agent_Agents] a
INNER JOIN ChildParent cp ON r.ParentID = cp.ID
)
SELECT
ID,
ParentID,
SomeName,
PLevel,
TopLevelFather
FROM ChildParent
Run Code Online (Sandbox Code Playgroud)
这会给你这样的节点(基于你的样本数据,稍微扩展):
ID ParentID SomeName PLevel TopLevelFather
20 -1 Top#20 1 20
4 -1 TOP#4 1 4
8 -1 TOP#8 1 8
7 8 ChildID = 7 2 8
3 7 ChildID = 3 3 8
2 4 ChildID = 2 2 4
9 20 ChildID = 9 2 20
5 9 ChildID = 5 3 20
1 5 ChildID = 1 4 20
Run Code Online (Sandbox Code Playgroud)
现在,如果从此CTE输出中选择特定的子节点,您将始终获得所需的所有信息 - 包括子级的"级别"及其顶级父节点.
Mik*_*son 16
不确定我理解你在寻找什么但它可能是这个.
;WITH c
AS (SELECT childid,
parentid,
parentid AS topParentID
FROM @myTable
WHERE childid = parentid
UNION ALL
SELECT T.childid,
T.parentid,
c.topparentid
FROM @myTable AS T
INNER JOIN c
ON T.parentid = c.childid
WHERE T.childid <> T.parentid)
SELECT childid,
topparentid
FROM c
ORDER BY childid
Run Code Online (Sandbox Code Playgroud)
这是一样的答案被marc_s用,我用你的表变量,你有这样的事实差别childID = parentID为根节点,其中由marc_s答案有parent_ID = null根的节点.在我看来,最好有parent_ID = null根节点.