Sql CTE递归到表A中的根目录,并在每次迭代时连接表B中的结果

Sql CTE递归到表A中的根目录,并在每次迭代时连接表B中的结果,sql,tsql,common-table-expression,Sql,Tsql,Common Table Expression,我是T-SQL中CTE的新手,但我喜欢它们。但是,对于我正在编写的这个特定存储过程,我无法获得正确的逻辑 给定带有列的表A: Id Name Inherits ... Id Name AId ... 其中,列继承存储一个int,该int是同一表中另一行的id 和表B中的列: Id Name Inherits ... Id Name AId ... 其中,AId是表a中某一行的外键 如何使用CTE从a中的任意行(x)开始,收集B中AId=x.Id的所有行,然后通过将x设置为x.Inheri

我是T-SQL中CTE的新手,但我喜欢它们。但是,对于我正在编写的这个特定存储过程,我无法获得正确的逻辑

给定带有列的
表A

Id Name Inherits ...
Id Name AId ...
其中,列继承存储一个int,该int是同一表中另一行的id

表B
中的列:

Id Name Inherits ...
Id Name AId ...
其中,AId是表a中某一行的外键

如何使用CTE从
a
中的任意行(
x
)开始,收集
B
AId=x.Id
的所有行,然后通过将x设置为
x.Inherits
指向的行,在a中向上递归。此操作应一直进行,直到
x.Inherits为NULL

因此,总体效果是,我希望返回起始A Id的相关B行,然后返回通过递归检查A的Inherits列发现的所有继承B行

我的想法是将CTE设置为从任意行递归到A的“根”,并且在每个递归调用中有一个到B的连接。这是我所能做到的:

WITH c 
AS
(

    SELECT A.Inherits,A.Id, B.Name, 1 AS Depth
    FROM tbl_A A
    INNER JOIN tbl_B B ON B.AId = A.Id
    WHERE A.Id = @ArbitraryStartingAId

    UNION ALL

    SELECT T.Inherits,T.Id, c.Name, c.Depth + 1 AS 'Level'
    FROM tbl_A T        
    INNER JOIN c ON T.Id = c.Inherits

)
SELECT *
FROM c 
产生:

1        4  b_val   1
11       1  b_val   2
NULL    11  b_val   3
其中
b_val
取自
表b行(y)
其中
@ArbitraryStartingAId=y.AId
。A上的递归正在工作,但在每次迭代时都没有拉入正确的对应B数据

如果有人能帮我重写这篇文章,得到我需要的结果,那就太好了


非常感谢

这里是我现在的位置,这是一个可能的答案,因为返回了正确的数据:

WITH c 
AS
(
    SELECT A.Inherits,A.Id, B.Name, 1 AS Depth
    FROM tbl_A A
    INNER JOIN tbl_B B ON B.AId = A.Id
    WHERE A.Id =@ArbitraryStartingAId

    UNION ALL

    SELECT T.Inherits,T.Id, T.Name, B.Name, c.Depth + 1 AS 'Level'
    FROM tbl_A T
    INNER JOIN tbl_B B ON B.AId = T.Id      
    INNER JOIN c ON T.Id = c.Inherits
)
SELECT DISTINCT *
FROM c ORDER BY Depth ASC
虽然它返回两次根级别B行时感觉有点脏,因此使用DISTINCT运算符将这些行过滤掉…?

假设我们有

CREATE TABLE A ( Id int, Name nvarchar(10), Inherits int );
CREATE TABLE B ( Id int, Name nvarchar(10), AId int );
还有一些数据:

INSERT A VALUES ( 1, 'one', 2 );
INSERT A VALUES ( 2, 'two', 3 );
INSERT A VALUES ( 3, 'three', null );
INSERT A VALUES ( 4, 'four', 3 );

INSERT B VALUES ( 1, 'B one', 1 );
INSERT B VALUES ( 2, 'B two', 2 );
INSERT B VALUES ( 3, 'B three', 3 );
INSERT B VALUES ( 4, 'B four', 4 );
我们可以在
a
上构建一个CTE,然后加入
B

WITH cteA AS 
(
    -- Anchor
    SELECT Id, Name, Inherits FROM A
    WHERE Id = 1
    UNION 
    -- Recursive
    SELECT A.Id, A.Name, A.Inherits FROM A
    INNER JOIN cteA ON A.Id = cteA.Inherits
)
SELECT * FROM cteA INNER JOIN B ON cteA.Id = B.AId;
要获取(锚定在
1
):


由于层次结构中似乎没有涉及到
B
,只需在
a
上执行标准的递归CTE,然后将其连接到
B
?这听起来是一个有趣的修复方法。你能提供一个代码示例作为答案吗。这样,如果正确的话,我可以选择它并给你代表