SQL Server 2014-深度递归父子自我加入

时间:2019-03-21 10:02:45

标签: sql sql-server recursion recursive-query

我正在尝试建立一个深度递归自联接查询。桌子像这样:

Id | ParentId
1  | NULL
2  | 1
3  | 1
4  | 2
5  | 3
6  | 8
7  | 9

对于ID 1,我的查询应获取1,2,3,4,5,因为它们是1的子代或1的子代。在给定的示例中,查询中不应包含6和7结果。

我尝试使用CTE,但是却得到大量重复:

WITH CTE AS (
    SELECT Id, ParentId
    FROM dbo.Table
    WHERE ParentId IS NULL
UNION ALL
    SELECT t.Id, t.ParentId
    FROM dbo.Table t
    INNER JOIN CTE c ON t.ParentId = c.Id
)
SELECT * FROM CTE

想法?

5 个答案:

答案 0 :(得分:1)

您可以尝试使用DISTINCT来过滤重复的行。

;WITH CTE AS (
    SELECT Id, ParentId
    FROM T
    WHERE ParentId IS NULL
UNION ALL
    SELECT t.Id, t.ParentId
    FROM T
    INNER JOIN CTE c ON t.ParentId = c.Id
)
SELECT DISTINCT Id, ParentId
FROM CTE

答案 1 :(得分:0)

使用CTE尝试以下查询,您可以在@parentID处设置parentId:

DECLARE @parentID INT = 1
;WITH cte AS 
(
    SELECT 
    t.ID
    , t.ParentId
    FROM @table t
),
cteParent AS
(
    SELECT 
    t.ID
    , t.ParentId
    FROM @table t
    WHERE t.ParentId IN (SELECT t1.ID FROM @table t1 WHERE T1.ParentId = @parentID)
)

SELECT 
DISTINCT c1.ID
, c1.ParentId
FROM cte c1
INNER JOIN cte c2 ON c2.ParentId = c1.ID
UNION ALL 
SELECT * 
FROM cteParent

以及示例数据:

DECLARE @table TABLE
(
    ID INT
    , ParentId INT
)

INSERT INTO @table
(
    ID,
    ParentId
)
VALUES
  (1, NULL )
, (2, 1 )

, (3, 1 )

, (4, 2 )

, (5, 3 )

, (6, 8 )

, (7, 9 )

输出:

ID  ParentId
1   NULL
2   1
3   1
4   2
5   3

答案 2 :(得分:0)

尝试使用此sql脚本生成父子层次结构

;WITH CTE(Id , ParentId)
AS
(
SELECT 1 , NULL  UNION ALL
SELECT 2 , 1     UNION ALL
SELECT 3 , 1     UNION ALL
SELECT 4 , 2     UNION ALL
SELECT 5 , 3     UNION ALL
SELECT 6 , 8     UNION ALL
SELECT 7 , 9
)
,Cte2
AS
(
    SELECT Id , 
          ParentId ,
         CAST('\'+ CAST(Id AS VARCHAR(MAX))AS VARCHAR(MAX)) AS [Hierarchy]
    FROM CTE
    WHERE ParentId IS NULL
    UNION ALL
    SELECT c1.Id , 
          c1.ParentId ,
        [Hierarchy]+'\'+ CAST(c1.Id AS VARCHAR(MAX)) AS [Hierarchy]
    FROM Cte2 c2
    INNER JOIN CTE c1
    ON  c1.ParentId = c2.Id
)
SELECT Id,
       RIGHT([Hierarchy],LEN([Hierarchy])-1) AS ParentChildHierarchy 
FROM Cte2

GO

结果

Id  ParentChildHierarchy
-------------------------
1    1
2    1\2
3    1\3
5    1\3\5
4    1\2\4

答案 3 :(得分:0)

我没有看到重复的东西。

您的代码在您提供的数据上返回以下内容:

Id  ParentId
1   
2   1
3   1
5   3
4   2

这就是你想要的。

Here是db <>小提琴。

代码如下:

WITH t as (
      SELECT *
      FROM (VALUES (1, NULL), (2, 1), (3, 1), (4, 2), (5, 3), (6, 8), (7, 9)
           ) v(id, parentId)
    ),
    CTE AS (
    SELECT Id, ParentId
    FROM t
    WHERE ParentId IS NULL
UNION ALL
    SELECT t.Id, t.ParentId
    FROM t
    INNER JOIN CTE c ON t.ParentId = c.Id
)
SELECT *
FROM CTE;

如果实际结果集中有重复项,则可能是原始表中有重复项。我建议在执行递归逻辑之前 删除它们:

with t as (
      select distinct id, parentid
      from <your query>
     ),
     . . .

然后运行递归逻辑。

答案 4 :(得分:0)

此查询将为您提供帮助

CREATE TABLE #table( ID INT, ParentId INT )

INSERT INTO #table(ID,ParentId)
VALUES (1, NULL ), (2, 1 ), (3, 1 ), (4, 2 ), (5, 3 ), (6, 8 ), (7, 9 )

;WITH CTE AS (
SELECT ID FROM #table WHERE PARENTID IS NULL
UNION ALL
SELECT T.ID FROM #table T  
INNER JOIN  #table T1 ON T.PARENTID =T1.ID 
) SELECT * FROM CTE