Sql server 递归SQL以获取原始替换行
我在Microsoft SQL Server 2008中使用T/SQL,并且有一个具有以下结构的用户许可证表:Sql server 递归SQL以获取原始替换行,sql-server,tsql,recursive-query,Sql Server,Tsql,Recursive Query,我在Microsoft SQL Server 2008中使用T/SQL,并且有一个具有以下结构的用户许可证表: LicenceID (PK, uniqueidentifier, not null) SupersededID (FK, uniqueidentifier, not null) …other licence related columns 当用户升级其许可证密钥时,将使用原始许可证ID填充该密钥。这可能会发生多次,因此始终可以追溯到发放的第一个许可证。许可证密钥也可能永远不会被取代
LicenceID (PK, uniqueidentifier, not null)
SupersededID (FK, uniqueidentifier, not null)
…other licence related columns
当用户升级其许可证密钥时,将使用原始许可证ID填充该密钥。这可能会发生多次,因此始终可以追溯到发放的第一个许可证。许可证密钥也可能永远不会被取代
我遇到的困难是,我需要能够查询licenses表中的所有行,并提取每个行的第一个原始许可证密钥
我相信这可以通过使用WITH方法递归调用查询来实现,但我并不完全清楚这个概念。。这就是我到目前为止所做的:
WITH c
AS (SELECT SupersededByID,
LicenceID,
LicenceID AS topParentID
FROM Licence
where SupersededBy IS NOT NULL
UNION ALL
SELECT l.SupersededBy,
l.LicenceID,
c.topparentid
FROM Licence AS l
INNER JOIN c
ON l.id = c.SupersededByID
WHERE T.SupersededByID IS NOT NULL)
SELECT *
FROM c
对于递归,必须从根记录开始,这些根记录是被取代的dbyid=NULL的记录。这些将为您提供当前的许可证,您需要追溯这些许可证 因此,基本的递归查询如下所示:
WITH c AS
(
SELECT SupersededById,
LicenceId,
LicenceId AS BaseId,
1 as Level
FROM Licence
WHERE SupersededById IS NULL
UNION ALL
SELECT l.SupersededById,
l.LicenceId,
c.BaseId,
c.Level + 1 as Level
FROM Licence AS l
INNER JOIN c ON l.SupersededById = c.LicenceId
)
SELECT * FROM c
这将为您提供带有两个附加列的所有记录:每次返回到被取代的许可证时,“级别”列都会上升。BaseId是在许可证跟踪上保持不变的常量
因此,使用这组数据,您可以查找每个BaseId具有最大级别的记录,这可以通过一个子选择来完成:
WITH c AS
(
SELECT SupersededById,
LicenceId,
LicenceId AS BaseId,
1 as Level
FROM Licence
where SupersededById ByIS NULL
UNION ALL
SELECT l.SupersededById,
l.LicenceId,
c.BaseId,
c.Level + 1 as Level
FROM Licence AS l
INNER JOIN c ON l.SupersededById = c.LicenceId
)
SELECT c1.LicenceId as OriginalLicence FROM c as c1
WHERE c1.Level = (SELECT MAX(c2.Level) FROM c as c2 WHERE c2.BaseId = c1.BaseId)
顺便说一句:如果你想从源表中获得更多的列,你只需要将它们添加到所有选择中。你考虑过使用SCD type 2表吗?这将避免递归。感谢您的故障排除。对于我试图在匆忙中提出一个问题来说,就这么多了。仅供参考:每次我在没有MaxRecursion选项的情况下发布递归CTE,OP在处理实际数据时都会进入默认的递归限制。哈博:我原希望100件再授权书能与现实世界中实际发生的情况相吻合,但对阿德斯堡来说:你知道如果不是这样,你必须做些什么:-谢谢@TToni,不过我想我还是遗漏了一些东西。。当我运行查询时,所有内容似乎都达到了1级结果,我知道有些许可证最多有4个。最后一个连接不应该是这个吗?l.Dbyd=c上的内部联接c。LicenceId@Adsborough:是的,你是对的。我写它的方式,第二部分永远不起作用,因为它将l.LicenseID与NULL进行比较,这总是错误的。将在答案中解决它。