我需要将最后一个子记录值更新为SQL中的父记录。我卡住了,并且没有点击任何想法来解决这个问题。
我有这样的表结构。
| id | parentID | Val|
1 NULL NULL
2 1 0
3 2 0
4 3 0
5 4 10
10 NULL NULL
11 11 101
我还附上了表脚本。
create table #table1 (id int, parentId int,Val int)
INSERT INTO #table1 VALUES (1,null,null),
(2,1,0)
,(3,2,0)
,(4,3,0)
,(5,4,10)
,(10, null,null)
,(11,10,101)
预期结果将是
| id | parentID | Val|
1 NULL 10
10 NULL 101
答案 0 :(得分:0)
我认为这就是你要求的:
WITH CTE1 (MasterParentID, ChildID, Length) AS
(
SELECT ID, ID, 0
FROM #table1
WHERE ParentID IS NULL
UNION ALL
SELECT CTE1.MasterParentID, T.ID, CTE1.Length + 1
FROM CTE1 JOIN #table1 T ON CTE1.ChildID = T.ParentID
),
CTE2 AS
(
SELECT
MasterParentID,
LastChildID = ChildID,
Rank = ROW_NUMBER() OVER (PARTITION BY MasterParentID ORDER BY Length DESC)
FROM CTE1
)
UPDATE #table1
SET Val = (SELECT Val FROM #table1 C WHERE C.ID = CTE2.LastChildID)
FROM CTE2 JOIN #table1 P ON CTE2.MasterParentID = P.ID
WHERE CTE2.Rank = 1
这将第1行的值设置为10,将第10行的值设置为101。
为了解释这个陈述,我将逐步建立起来。
WITH CTE1 (MasterParentID, ChildID, Length) AS
(
SELECT ID, ID, 0
FROM #table1
WHERE ParentID IS NULL
UNION ALL
SELECT CTE1.MasterParentID, T.ID, CTE1.Length + 1
FROM CTE1 JOIN #table1 T ON CTE1.ChildID = T.ParentID
)
SELECT * FROM CTE1
此查询使用common table expression(CTE)以递归方式将父行连接到子行。结果集是:
MasterParentID ChildID Length
1 1 0
10 10 0
10 11 1
1 2 1
1 3 2
1 4 3
1 5 4
前两行由SELECT ID, ID, 0 FROM #table1 WHERE ParentID IS NULL
返回。通过递归地将前两行连接到#table1
来返回剩余的行。
Length
列表示从MasterParentID
到ChildID
的链的长度。它将在步骤2中用于识别每个链中的最后一个链接。
WITH CTE1 (MasterParentID, ChildID, Length) AS
(
/* as above... */
),
CTE2 AS
(
SELECT
MasterParentID,
LastChildID = ChildID,
Rank = ROW_NUMBER() OVER (PARTITION BY MasterParentID ORDER BY Length DESC)
FROM CTE1
)
SELECT *
FROM CTE2
WHERE CTE2.Rank = 1
此查询采用步骤1中的结果集,按MasterParentID
对其进行分区,并仅返回每个分区中Length
(排名#1)最高的行。结果集是:
MasterParentID LastChildID Rank
1 5 1
10 11 1
WITH CTE1 (MasterParentID, ChildID, Length) AS
(
/* as above... */
),
CTE2 AS
(
/* as above... */
)
UPDATE #table1
SET Val = (SELECT Val FROM #table1 C WHERE C.ID = CTE2.LastChildID)
FROM CTE2 JOIN #table1 P ON CTE2.MasterParentID = P.ID
WHERE CTE2.Rank = 1
此语句采用步骤2中的结果集,并使用它来更新#table1
。