簡體   English   中英

具有遞歸 CTE 的 SQL 組

[英]SQL group with Recursive CTE

我正在研究 SQL Server 2008。我相信我的 Q 的答案在於遞歸 CTE,但任何解決方案都將不勝感激。

在下面的 sam_DB.dbo.example 表中,PID 不為空,它鏈接回一個 ID

    ID     | PID   
    ------ | ------
    1      | NULL  
    2      | 1     
    3      | 2     
    4      | 3     
    5      | NULL  
    6      | 5     
    7      | 6     
    8      | NULL  
    9      | NULL  
    10     | 9     

我希望我的輸出有一個新字段 (CID),它將從 PID 到 ID 的鏈接鏈中的每條記錄標識為組的一部分,如下所示。

   ID     | PID    | CID   
   ------ | ------ | ------
   1      | NULL   | 1     
   2      | 1      | 1     
   3      | 2      | 1     
   4      | 3      | 1     
   5      | NULL   | 2     
   6      | 5      | 2     
   7      | 6      | 2     
   8      | NULL   | 3     
   9      | NULL   | 4     
   10     | 9      | 4     

你是對的,你需要一個 CTE。

您需要定義查詢的第一部分以選擇頂級記錄(即那些沒有父級的記錄):

select ID, PID, ID
from @t
where PID is null

然后,對於添加到結果 CTE 的每一行(即首先對於上述查詢返回的那些記錄,然后再次對於查詢的第二部分添加的每個新行,每次添加重復,直到沒有新添加)您應該從源表中添加父 ID 與先前添加的行的 ID 匹配的所有記錄。

select t.ID, t.PID, c.CID
from cte c
inner join @t t
on t.PID = c.ID

除了這個邏輯之外,唯一需要注意的另一件事是第一個表達式的 CID 列采用記錄的 ID,而對於第二個表達式返回的那些記錄,它采用父記錄的 CID。

完整代碼

--set up the demo data
declare @t table (ID int not null, PID int null)
insert @t 
values (1, null)
, (2,1)
, (3,2)
, (4,3)
, (5,null)
, (6,5)
, (7,6)
, (8,null)
, (9,null)
, (10,9)

--actual demo
;with cte (ID, PID, CID) as (

    --select out top most (ancestor) records; setting CID to ID (since they're the oldest ancestor in their own chain, given they don't have parents)
    select ID, PID, ID
    from @t
    where PID is null

    union all

    --select each record that is a child of the record we previously selected, holding the ancestor as the parent record's ancestor
    select t.ID, t.PID, c.CID
    from cte c
    inner join @t t
    on t.PID = c.ID
)
select * 
from CTE 
order by ID

你必須使用Common text expression With Row_Number Window 函數

CREATE TABLE #TblTemp(ID int,PID int)


INSERT INTO #TblTemp(ID ,PID ) VALUES (1,NULL),(2,1),(3,1),(4,3),(5,NULL),(6,5),(7,6),(8,NULL),(9,NULL),(10,9)


;WITH CTE (ID, PID, CID) AS (

    SELECT ID, PID, ROW_NUMBER() OVER(ORDER BY ID) RN
    FROM #TBLTEMP
    WHERE PID IS NULL

    UNION ALL

    SELECT T.ID, T.PID, C.CID 
    FROM CTE C
    INNER JOIN #TBLTEMP T
    ON T.PID = C.ID
)
SELECT * 
FROM CTE 
ORDER BY ID

我將發布一些簡單的示例——展示如何為父/子組的錯誤鏈接或損壞的部分創建遞歸分組

聲明@t table (item varchar(2), tr int null, rc int null) insert @t select 'a',1,9 -- 沒有鏈接 'a' - 是組父插入 @t select 'b',2 ,1 -- 鏈接到 'a' 插入 @t select 'c',3,2 -- 鏈接到 'b' 插入 @t select 'd',4,3 -- 鏈接到 'd' 插入 @t select ' e',6,7 -- 沒有鏈接 'e' - 是一個不同的組 insert @t select 'f',8,2 -- 鏈接到 'c'

-- 基於父項名稱的 grn-group 名稱; -- 基於父項 ID 的 gid-group 名稱; -- tr-transactionID ; rc-recursiveID; -- rc_New-要使用的新遞歸ID; rc_Old - 原始遞歸ID

;with cte as ( select grn=s.item, gid=s.tr, s.item, s.tr, rc_New= t.tr, rc_Old=s.rc from @ts left join @tt on t.tr=s .rc where (t.tr is NULL or s.rc is NULL) union all select c.grn, c.gid,s.item, s.tr, rc_New=s.rc, rc_Old=s.rc from cte c join @ts on s.rc=c.tr where s.rc is not NULL ) select * from cte order by 2,3

選項(MAXRECURSION 32767,FAST 100)

暫無
暫無

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

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