C# FOREACH递归SQL语句
我有一个看起来很简单的问题,但我尝试过的解决方案让我在执行方面有所欠缺。速度看起来很小(不确定我是否满足您的所有要求,但这是一个开始。告诉我它是否符合您的要求,或者是否生成的数字不正确C# FOREACH递归SQL语句,c#,sql,tsql,sql-server-2008,C#,Sql,Tsql,Sql Server 2008,我有一个看起来很简单的问题,但我尝试过的解决方案让我在执行方面有所欠缺。速度看起来很小(不确定我是否满足您的所有要求,但这是一个开始。告诉我它是否符合您的要求,或者是否生成的数字不正确 ;with C as ( select ID, ParentID, ControlNum, ParentControlNum, row_number() over(order by ParentID, ID) - 1 as rn fr
;with C as
(
select ID,
ParentID,
ControlNum,
ParentControlNum,
row_number() over(order by ParentID, ID) - 1 as rn
from YourTable
)
update C1
set ControlNum = C1.rn,
ParentControlNum = case when C1.ParentID is null
then C1.rn
else C2.rn
end
from C as C1
left outer join C as C2
on C1.ParentID = C2.ID
使用稍微修改的输入在SE数据上运行:
第2版
首先是一个递归CTER
,它构建一个字符串,在为ControlNum
生成值时用作order by。之后,它与上述内容基本相同
;with R as
(
select ID,
ParentID,
cast(ID as varchar(max)) as Sort
from YourTable
where ParentID is null
union all
select T.ID,
T.ParentID,
R.Sort+cast(T.ID as varchar(max))
from YourTable as T
inner join R
on R.ID = T.ParentID
),
C as
(
select ID,
ParentID,
row_number() over(order by Sort) - 1 as rn
from R
)
update T
set ControlNum = C1.rn,
ParentControlNum = case when C1.ParentID is null
then C1.rn
else C2.rn
end
from YourTable as T
inner join C as C1
on T.ID = C1.ID
left outer join C as C2
on T.ParentID = C2.ID
在此处测试:
注意:我想这是处理某些数据的一次性操作,因为您很难添加新节点,同时也很难像这样维护编号。例如,如果您向第一个节点添加新的子节点,则必须为“下面”的所有节点分配all
ControlNum+=1
并重新分配所有的ParentControlNum
您能添加一些示例数据吗?更新前的样子和更新后的样子。我不清楚“生成ControlNum值以遵守父子关系”是什么意思@MikaelEriksson添加了一点解释的示例数据。这是朝着正确方向迈出的一大步。但这并不能完全解决我的问题,我已将我的问题扩展为更明确的问题。这确实是在处理前对数据进行最终排序的一次重演。这确实有效,但速度稍慢,可能是因为字符串比较。我正在考虑是否可以从第一个版本中获取数据,按ParentControlNum排序,然后在结果上使用row_number()。不管是谁,请考虑一下未来的进展。再次感谢您提供的有效答案。
ID ParentId ControlNum ParentControlNum
8C821027-A6F9-E011-AB48-B499BAE13A62 756F981E-A6F9-E011-AB48-B499BAE13A62 22 21
D7DB6033-A6F9-E011-AB48-B499BAE13A62 756F981E-A6F9-E011-AB48-B499BAE13A62 24 21
D2E36033-A6F9-E011-AB48-B499BAE13A62 C9E36033-A6F9-E011-AB48-B499BAE13A62 58 57
8FE66033-A6F9-E011-AB48-B499BAE13A62 58E66033-A6F9-E011-AB48-B499BAE13A62 69 68
37EC6033-A6F9-E011-AB48-B499BAE13A62 2FEC6033-A6F9-E011-AB48-B499BAE13A62 86 85
41EC6033-A6F9-E011-AB48-B499BAE13A62 2FEC6033-A6F9-E011-AB48-B499BAE13A62 88 85
DDED6033-A6F9-E011-AB48-B499BAE13A62 BCED6033-A6F9-E011-AB48-B499BAE13A62 95 94
DC69981E-A6F9-E011-AB48-B499BAE13A62 NULL 0 0
166A981E-A6F9-E011-AB48-B499BAE13A62 NULL 1 1
4D6A981E-A6F9-E011-AB48-B499BAE13A62 NULL 2 2
856A981E-A6F9-E011-AB48-B499BAE13A62 NULL 3 3
F56A981E-A6F9-E011-AB48-B499BAE13A62 NULL 4 4
2E6B981E-A6F9-E011-AB48-B499BAE13A62 NULL 5 5
666B981E-A6F9-E011-AB48-B499BAE13A62 NULL 6 6
9D6B981E-A6F9-E011-AB48-B499BAE13A62 NULL 7 7
1
4
7
8
5
2
6
3
1
2
3
4
5
6
7
8
;with C as
(
select ID,
ParentID,
ControlNum,
ParentControlNum,
row_number() over(order by ParentID, ID) - 1 as rn
from YourTable
)
update C1
set ControlNum = C1.rn,
ParentControlNum = case when C1.ParentID is null
then C1.rn
else C2.rn
end
from C as C1
left outer join C as C2
on C1.ParentID = C2.ID
;with R as
(
select ID,
ParentID,
cast(ID as varchar(max)) as Sort
from YourTable
where ParentID is null
union all
select T.ID,
T.ParentID,
R.Sort+cast(T.ID as varchar(max))
from YourTable as T
inner join R
on R.ID = T.ParentID
),
C as
(
select ID,
ParentID,
row_number() over(order by Sort) - 1 as rn
from R
)
update T
set ControlNum = C1.rn,
ParentControlNum = case when C1.ParentID is null
then C1.rn
else C2.rn
end
from YourTable as T
inner join C as C1
on T.ID = C1.ID
left outer join C as C2
on T.ParentID = C2.ID