条件递归 SQL Select
Conditional Recursive SQL Select
考虑以下数据库 table。它由 3 列组成:Id、ParentId、Enabled.
我想生成类似于以下的结果集。基本上,对于每个具有 Parent ID 的记录,我想显示一个附加列 Enabled Parent Id。这一列基本上需要递归检查键的层次结构,并在找到 Enabled = True 的键时停止。
我希望这可以即时实现,而不需要在 table.
中添加任何额外的计算列
也许这可以使用 CTE.
来实现
试试这个 CTE 查询:
WITH T1 as
(SELECT id,
parentId,
NULL as EnabledParentId,
ParentID as NextParent
FROM T
WHERE ParentID is not null
UNION ALL
SELECT T1.id,
T1.parentId,
CASE WHEN T.enabled = 1
THEN T.ID
ELSE NULL END
as EnabledParentId,
T.ParentID as NextParent
FROM T1
JOIN T ON T1.NextParent = T.Id
WHERE (nextParent is not Null) and (EnabledParentId IS NULL)
)
SELECT ID,
ParentID,
EnabledParentID
FROM T1
WHERE EnabledParentId IS NOT NULL
OR NextParent IS NULL
ORDER BY ID;
DECLARE @myTable TABLE
(
Id INT NOT NULL,
ParentId INT NOT NULL,
EnabledParentId INT
)
DECLARE myCursor CURSOR FOR
SELECT Id
FROM T
WHERE ParentId IS NOT NULL
ORDER BY Id;
OPEN myCursor;
DECLARE @currentId INT;
FETCH NEXT FROM myCursor INTO @currentId;
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @Exists BIT = 0;
DECLARE @ParentId INT
SELECT @ParentId = ParentId
FROM T
WHERE Id = @currentId
WHILE (@ParentId IS NOT NULL AND @Exists = 0)
BEGIN
IF EXISTS(SELECT * FROM T WHERE Id = @ParentId AND IsEnabled = 1)
BEGIN
SET @Exists = 1
END
ELSE
BEGIN
SELECT @ParentId = ParentId
FROM T
WHERE Id = @ParentId
END
IF (@Exists = 1 OR @ParentId IS NULL)
BEGIN
INSERT INTO @myTable
SELECT Id, ParentId, @ParentId
FROM T
WHERE Id = @currentId
END
END
FETCH NEXT FROM myCursor INTO @currentId;
END
CLOSE myCursor;
DEALLOCATE myCursor;
SELECT *
FROM @myTable
ORDER BY 1
考虑以下数据库 table。它由 3 列组成:Id、ParentId、Enabled.
我想生成类似于以下的结果集。基本上,对于每个具有 Parent ID 的记录,我想显示一个附加列 Enabled Parent Id。这一列基本上需要递归检查键的层次结构,并在找到 Enabled = True 的键时停止。
我希望这可以即时实现,而不需要在 table.
中添加任何额外的计算列也许这可以使用 CTE.
来实现试试这个 CTE 查询:
WITH T1 as
(SELECT id,
parentId,
NULL as EnabledParentId,
ParentID as NextParent
FROM T
WHERE ParentID is not null
UNION ALL
SELECT T1.id,
T1.parentId,
CASE WHEN T.enabled = 1
THEN T.ID
ELSE NULL END
as EnabledParentId,
T.ParentID as NextParent
FROM T1
JOIN T ON T1.NextParent = T.Id
WHERE (nextParent is not Null) and (EnabledParentId IS NULL)
)
SELECT ID,
ParentID,
EnabledParentID
FROM T1
WHERE EnabledParentId IS NOT NULL
OR NextParent IS NULL
ORDER BY ID;
DECLARE @myTable TABLE
(
Id INT NOT NULL,
ParentId INT NOT NULL,
EnabledParentId INT
)
DECLARE myCursor CURSOR FOR
SELECT Id
FROM T
WHERE ParentId IS NOT NULL
ORDER BY Id;
OPEN myCursor;
DECLARE @currentId INT;
FETCH NEXT FROM myCursor INTO @currentId;
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @Exists BIT = 0;
DECLARE @ParentId INT
SELECT @ParentId = ParentId
FROM T
WHERE Id = @currentId
WHILE (@ParentId IS NOT NULL AND @Exists = 0)
BEGIN
IF EXISTS(SELECT * FROM T WHERE Id = @ParentId AND IsEnabled = 1)
BEGIN
SET @Exists = 1
END
ELSE
BEGIN
SELECT @ParentId = ParentId
FROM T
WHERE Id = @ParentId
END
IF (@Exists = 1 OR @ParentId IS NULL)
BEGIN
INSERT INTO @myTable
SELECT Id, ParentId, @ParentId
FROM T
WHERE Id = @currentId
END
END
FETCH NEXT FROM myCursor INTO @currentId;
END
CLOSE myCursor;
DEALLOCATE myCursor;
SELECT *
FROM @myTable
ORDER BY 1