我在Microsoft SQL Server 2008中使用T / SQL,并且拥有一个用户许可证表,其中包含以下结构:
LicenceID (PK, uniqueidentifier, not null)
SupersededID (FK, uniqueidentifier, not null)
…other licence related columns
当用户升级其许可证密钥时,SupersededID将填充原始LicenceID。这可能会多次发生,因此将始终追溯到已发布的第一个许可证。许可证密钥也可能永远不会被取代。
我遇到的困难是我需要能够查询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
答案 0 :(得分:2)
对于递归,您必须从根记录开始,这些记录是SupersededById = 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)
BTW:如果你想要源表中的其他列,你只需要将它们添加到所有SELECT中。