gpt4 book ai didi

sql - 在递归 SQL 表中查找最低公共(public)父级

转载 作者:行者123 更新时间:2023-12-01 09:10:59 25 4
gpt4 key购买 nike

假设我有一个递归表(例如,员工和经理)和一个大小为 0..n 的 ID 列表。如何找到这些 id 的最低共同父项?

例如,如果我的表格如下所示:

Id | ParentId
---|---------
1 | NULL
2 | 1
3 | 1
4 | 2
5 | 2
6 | 3
7 | 3
8 | 7

那么下面这组 id 会导致下面的结果(第一个是极端情况):

[]      => 1 (or NULL, doesn't really matter)
[1] => 1
[2] => 2
[1,8] => 1
[4,5] => 2
[4,6] => 1
[6,7,8] => 3

如何做到这一点?

编辑:请注意,在所有情况下,父项都不是正确的术语。它是树上所有路径中最低的公共(public)节点。最低公共(public)节点也可以是节点本身(例如在 [1,8] => 1 的情况下,节点 1 不是节点 的父节点1 但节点 1 本身)。

亲切的问候,罗纳德

最佳答案

这是一种方法;它使用递归 CTE 来查找节点的祖先,并在输入值上使用“CROSS APPLY”来获取共同祖先;您只需更改 @ids (表变量)中的值:

----------------------------------------- SETUP
CREATE TABLE MyData (
Id int NOT NULL,
ParentId int NULL)

INSERT MyData VALUES (1,NULL)
INSERT MyData VALUES (2,1)
INSERT MyData VALUES (3,1)
INSERT MyData VALUES (4,2)
INSERT MyData VALUES (5,2)
INSERT MyData VALUES (6,3)
INSERT MyData VALUES (7,3)
INSERT MyData VALUES (8,7)

GO
CREATE FUNCTION AncestorsUdf (@Id int)
RETURNS TABLE
AS
RETURN (
WITH Ancestors (Id, ParentId)
AS (
SELECT Id, ParentId
FROM MyData
WHERE Id = @Id
UNION ALL
SELECT md.Id, md.ParentId
FROM MyData md
INNER JOIN Ancestors a
ON md.Id = a.ParentId
)
SELECT Id FROM Ancestors
);
GO
----------------------------------------- ACTUAL QUERY
DECLARE @ids TABLE (Id int NOT NULL)
DECLARE @Count int
-- your data (perhaps via a "split" udf)
INSERT @ids VALUES (6)
INSERT @ids VALUES (7)
INSERT @ids VALUES (8)

SELECT @Count = COUNT(1) FROM @ids
;
SELECT TOP 1 a.Id
FROM @ids
CROSS APPLY AncestorsUdf(Id) AS a
GROUP BY a.Id
HAVING COUNT(1) = @Count
ORDER BY a.ID DESC

如果节点不严格升序,则更新:

CREATE FUNCTION AncestorsUdf (@Id int)
RETURNS @result TABLE (Id int, [Level] int)
AS
BEGIN
WITH Ancestors (Id, ParentId, RelLevel)
AS (
SELECT Id, ParentId, 0
FROM MyData
WHERE Id = @Id
UNION ALL
SELECT md.Id, md.ParentId, a.RelLevel - 1
FROM MyData md
INNER JOIN Ancestors a
ON md.Id = a.ParentId
)

INSERT @result
SELECT Id, RelLevel FROM Ancestors

DECLARE @Min int
SELECT @Min = MIN([Level]) FROM @result

UPDATE @result SET [Level] = [Level] - @Min

RETURN
END
GO

SELECT TOP 1 a.Id
FROM @ids
CROSS APPLY AncestorsUdf(Id) AS a
GROUP BY a.Id, a.[Level]
HAVING COUNT(1) = @Count
ORDER BY a.[Level] DESC

关于sql - 在递归 SQL 表中查找最低公共(public)父级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1005761/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com