考虑下表:
SELECT [ItemID]
,[ParentID]
,[PolicyID]
,[PolicyRoot]
FROM [AdventureWorks2008R2].[dbo].[Example]
ItemID ParentID PolicyID PolicyRoot
----------- ----------- ---------- ----------
1 NULL default 1
2 1 b 1
3 1 c 0
4 NULL d 1
5 3 e 0
6 3 f 1
7 NULL g 0
我正在尝试从PolicyID
的每个项目中选择PolicyRoot = 1
,以防PolicyRoot = 0
我需要PolicyID
使用ParentID
。这是递归的......
使用功能
CREATE FUNCTION dbo.Policies(@ItemID INT) RETURNS VARCHAR(10)
AS
BEGIN
DECLARE @ParentID INT, @PolicyRoot BIT, @PolicyID VARCHAR(10)
SELECT @ParentID = ParentID
, @PolicyRoot = PolicyRoot
, @PolicyID = PolicyID
FROM [dbo].[Example]
WHERE ItemID = @ItemID
IF @PolicyRoot != 1
SELECT @PolicyID = dbo.Policies(@ParentID)
RETURN @PolicyID
END;
GO
SELECT ItemID
, dbo.Policies(ItemID) AS Policy
FROM [dbo].[Example];
ItemID Policy
----------- ----------
1 default
2 b
3 default
4 d
5 default
6 f
7 NULL
我正在尝试将此功能重写为CTE,但我还没有任何CTE知识。我已经阅读了多个CTE,但我没有一个线索如何管理条件CTE。就我而言,我对UNION ALL
并不熟悉(足够)。
WITH Policies (ItemID, PolicyID) AS (
SELECT ItemID
, PolicyID
FROM dbo.Example
UNION ALL
...
)
SELECT ItemID
, PolicyID
FROM Policies;
有人可以用简单的步骤向我解释这样一个CTE的工作原理并将我推向正确的方向吗?
答案 0 :(得分:2)
递归CTE通过加入自身来工作,使用UNION ALL
来整理结果。
您可以使用yourtable填充递归查询的初始数据集
select * from yourtable
然后使用UNION ALL
添加更多结果
select c.ItemID, t2.ParentID, t2.PolicyID, t2.PolicyRoot
from yourtable t2
inner join c on c.ParentID = t2.ItemID
where c.PolicyRoot=0
并且递归发生在这里 - 此查询的结果一次又一次地通过此查询,直到MAXRECURSION
限制,或者当没有添加更多结果时。
;with c as
(
select * from yourtable
union all
select c.ItemID, t2.ParentID, t2.PolicyID, t2.PolicyRoot
from yourtable t2
inner join c on c.ParentID = t2.ItemID
where c.PolicyRoot=0
)
select t.ItemID, c.PolicyID
from yourtable t
left join c on t.ItemID = c.ItemID
and c.PolicyRoot=1