0

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

Table A与列一起给出:

Id Name Inherits ...

列 Inherits 存储一个 int,它是同一个表中另一行的 id。

Table B与列:

Id Name AId ...

其中 AId 是表 A 中一行的外键。

如何使用 CTE 从 in 中的任意行 ( x) 开始,收集where 中A的所有行,然后通过将 x 设置为指向的行在 A 中向上递归。这应该一直持续到.BAId = x.Idx.Inheritsx.Inherits IS NULL

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

我的想法是设置 CTE 以从任意行递归到 A 的“根”,并且在每个递归调用内部都有一个到 B 的 JOIN。据我所知:

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

Whereb_val取自Table B row (y)where @ArbitraryStartingAId = y.AId。A 上的递归正在工作,但在每次迭代时都没有提取正确的相应 B 数据。

如果有人可以帮助重写它以产生我需要的结果,那就太好了。

非常感谢

4

2 回答 2

2

假设我们有

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 );

我们可以在 上构建 CTE A然后加入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):

Id          Name       Inherits    Id          Name       AId
----------- ---------- ----------- ----------- ---------- -----------
1           one        2           1           B one      1
2           two        3           2           B two      2
3           three      NULL        3           B three    3
于 2012-12-04T15:29:07.283 回答
0

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

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 运算符将它们过滤掉......??

于 2012-11-29T15:52:42.453 回答