我正在研究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
答案 0 :(得分:1)
你是正确的,你需要一个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
答案 1 :(得分:0)
你必须使用通用文字表达使用 Row_Number 窗口功能
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
答案 2 :(得分:0)
我将发布一些简单的示例 -显示如何为父/子组的错误链接或损坏的块创建递归分组
声明@t表(item varchar(2),tr int null,rc int null) 插入@t选择'a',1,9-无链接'a'-是组父级 插入@t选择'b',2,1-链接到'a' 插入@t选择'c',3,2-链接到'b' 插入@t选择'd',4,3-链接到'd' 插入@t选择'e',6,7-无链接'e'-是不同的组 插入@t选择'f',8,2-链接到'c'
-基于父项名称的grn-group名称; -基于父项id的gid-group名称; -tr-transactionID; rc-recursiveID; -使用的rc_New-new recursiveID; rc_Old-原始递归ID
;使用cte作为 ( 从@t s中选择grn = s.item,gid = s.tr,s.item,s.tr,rc_New = t.tr,rc_Old = s.rc t.tr = s.rc上的左连接@t t,其中(t.tr为NULL或s.rc为NULL) 全部合并 选择c.grn,c.gid,s.item,s.tr,rc_New = s.rc,rc_Old = s.rc 来自cte c join @t s s.rc = c.tr,其中s.rc不为NULL ) 从CTE订单中选择*,按2,3
选项(MAXRECURSION 32767,快速100)