[英]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.