我正在研究SQL Server 2008.我相信我的Q的答案在于递归CTE,但任何解决方案都会非常感激。
在下面的sam_DB.dbo.example表中,PID不为null,它会链接回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
你必须使用Common文本表达式和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
你是正确的,你需要一个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
我将发布一些简单的示例 - 演示如何为父/子组的错误链接或损坏的片段创建递归分组
声明@t table(item varchar(2),tr int null,rc int null)insert @t select'a',1,9 - no links'a' - 是group parent insert @t select'b',2 ,1 - 链接到'a'插入@t select'c',3,2 - 链接到'b'插入@t选择'd',4,3 - 链接到'd'插入@t选择' e',6,7 - 没有链接'e' - 是一个不同的组插入@t select'f',8,2 - 链接到'c'
- 基于父项名称的grn-group名称; - 基于父项id的gid-group名称; - tr-transactionID; RC-recursiveID; - 使用rc_New-new recursiveID; rc_Old - 原始recursiveID
;使用cte as(选择grn = s.item,gid = s.tr,s.item,s.tr,rc_New = t.tr,rc_Old = s.rc来自@ts left join @tt on t.tr = s .rc其中(t.tr为NULL或s.rc为NULL)union cte c join中选择c.grn,c.gid,s.item,s.tr,rc_New = s.rc,rc_Old = s.rc @ts on s.rc = c.tr,其中s.rc不为NULL)从cte order中选择*为2,3
选项(MAXRECURSION 32767,FAST 100)