首页 文章

重写函数到条件CTE

提问于
浏览
0

Considering following table:

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

我正试图从 PolicyRoot = 1 的每个项目中选择 PolicyID ,如果 PolicyRoot = 0 我需要从 ParentID 使用 PolicyID . 这是递归的......

Working with a function:

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知识 . 我've read into multiple CTE'但我没有得到,我对 UNION ALL 并不熟悉(足够) .

WITH Policies (ItemID, PolicyID) AS (
    SELECT  ItemID
    ,       PolicyID
    FROM    dbo.Example

    UNION ALL

    ...
)
SELECT  ItemID
,       PolicyID
FROM    Policies;

有人可以用简单的步骤向我解释这样一个CTE的工作原理并将我推向正确的方向吗?

1 回答

  • 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
    

相关问题