簡體   English   中英

如何使用遞歸邏輯僅返回sql表中的Root行(SQL Server 2008 R2)

[英]How to use recursive logic to return only the Root row in a sql table (SQL Server 2008 R2)

這是針對SQL Server 2008 R2的,我是SQL的新手,所以請盡可能具體。

Table1內置了一些遞歸結構,其中ParentIdNull表示它是根,或者ParentIdTable1中另一行的Id (表示其為子代)。

數據集示例:

Table1Id    ParentId
--------------------------------------------
1           NULL
2           1
3           1
4           2
5           NULL
6           2
7           6
8           NULL
9           8

在上面的示例中,表格具有以下帶有3個根節點的樹結構:

Root                    1                 5                 8
Child(teir1)        2       3                               9
Child(teir2)      4   6
Child(tier3)          7
....

給定任何行ID,是否有辦法僅返回“根”行? 例如:

InputId      ReturnedRowId
----------------------------
1             1
2             1
3             1
4             1
5             5
6             1
7             1
8             8
9             8

任何幫助,將不勝感激。

您可以使用CTE遍歷層次結構

    IF OBJECT_ID('tempdb..#testData') IS NOT NULL
        DROP TABLE #testData
    CREATE TABLE #testData (  
         Table1Id           INT
        ,ParentId           INT NULL
    )

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


    DECLARE @InputId INT

    SET @InputId = 2  --<<--Change this as appropriate

    ;WITH cteTraverse
    AS
    (
        SELECT
            T.Table1Id, T.ParentId
        FROM
            #testData T
        WHERE
            Table1Id = @InputId
        UNION ALL
        SELECT
            T1.Table1Id, T1.ParentId
        FROM
            #testData T1
        INNER JOIN
            cteTraverse T2 ON T1.Table1Id = T2.ParentId 
    )
    SELECT
        @InputId '@InputId', Table1Id 'ReturnedRowId'
    FROM
        cteTraverse
    WHERE
        ParentId IS NULL

這個查詢完成工作。

with CTE as 
(
    Select Table1ID as ID, Table1ID as Ancestor, 0 as level
    from Table1

    UNION ALL

    Select ID, ParentID, level + 1
    from Table1
        inner join CTE on CTE.Ancestor = Table1.Table1ID
    where ParentID is not NULL
)
,
R_only as 
(
Select ID as ID, MAX(level) as max_level 
from CTE 
group by ID
)

select CTE.ID, Ancestor 
from CTE inner join R_only on CTE.ID = R_only.ID and CTE.level = R_only.max_level
order by CTE.ID

這是一個腳本,可為您擁有的節點表找到根節點。 它能做什么:

  • 在第一個CTE中,遞歸節點,直到找到父節點。 遞歸跟蹤列level的深度。
  • 在第二個CTE中,確定每個節點的最大深度: max_level 這是確定父級的深度。
  • 選擇最大深度的節點。
CREATE TABLE #tree(table1_id INT PRIMARY KEY,parent_id INT);
INSERT INTO #tree(table1_id,parent_id)VALUES
    (1,NULL),(2,1),(3,1),(4,2),(5,NULL),(6,2),(7,6),(8,NULL),(9,8);

;WITH cte_tr AS (
    SELECT table1_id, parent_id, level=0
    FROM #tree
    UNION ALL
    SELECT t_c.table1_id, t_p.parent_id, level=t_c.level+1
    FROM cte_tr AS t_c
         INNER JOIN #tree AS t_p ON
             t_p.table1_id=t_c.parent_id
    WHERE t_p.parent_id IS NOT NULL
),
cte_ml AS (
    SELECT table1_id, max_level=MAX(level)
    FROM cte_tr
    GROUP BY table1_id
)
SELECT cte_tr.table1_id, root_node=ISNULL(cte_tr.parent_id,cte_tr.table1_id)
FROM cte_tr 
     INNER JOIN cte_ml ON 
         cte_ml.table1_id=cte_tr.table1_id AND 
         cte_ml.max_level=cte_tr.level
ORDER BY cte_tr.table1_id

DROP TABLE #tree;

結果:

+-----------+-----------+
| table1_id | root_node |
+-----------+-----------+
|         1 |         1 |
|         2 |         1 |
|         3 |         1 |
|         4 |         1 |
|         5 |         5 |
|         6 |         1 |
|         7 |         1 |
|         8 |         8 |
|         9 |         8 |
+-----------+-----------+

使用“開始於”和“事先連接”。 在此處查看此文檔

http://psoug.org/reference/connectby.html

我不確定除Oracle以外的其他數據庫是否可以使用“ connect by”。 看看這個。

您也可以嘗試with子句。 有人在這里嘗試過。

SQL Server中ORACLE的PRIOR CONNECT的仿真

與這樣的作品

with query1 as (select .... from .... where ....),
     query2 as (select .... from .... where ....)
select ...
  from query1 q1,
       query2 q2
 where q1.xxxxx = q2.xxxx

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM