批量更新ParentKey:将缺失父键的行关联至同批次最近父行
解决方案:批量更新缺失的ParentKey记录
针对你的需求,可以通过窗口函数+CTE的方式高效完成批量更新,核心思路是先为每个需要更新的行计算出同批次内最近的父行DocID,再执行更新操作。
方法一:兼容全版本SQL Server的MAX窗口函数方案
这个方案无需依赖高版本特性,适用于所有支持窗口函数的SQL Server版本:
WITH BatchParentLookup AS ( SELECT DocID, -- 计算同批次内,当前行及之前最近的LevelNum=1的DocID MAX(CASE WHEN LevelNum = 1 THEN DocID ELSE NULL END) OVER ( PARTITION BY BatchID ORDER BY PosInBatch ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS TargetParentKey FROM #TEMPBATCH ) UPDATE t SET t.ParentKey = bpl.TargetParentKey FROM #TEMPBATCH t JOIN BatchParentLookup bpl ON t.DocID = bpl.DocID WHERE t.LevelNum = 0 AND t.ParentKey = 0;
逻辑说明:
PARTITION BY BatchID:按批次分组,确保只在同批次内查找父行ORDER BY PosInBatch:按行的位置顺序处理,保证"最近"的逻辑MAX(CASE ...):当遇到LevelNum=1的父行时,记录其DocID;后续子行的MAX值会继承这个父ID,直到下一个父行出现,完美实现"最近父行"的匹配
方法二:SQL Server 2022+专属的LAST_VALUE方案
如果使用SQL Server 2022及以上版本,可以用LAST_VALUE结合IGNORE NULLS简化逻辑:
WITH BatchParentLookup AS ( SELECT DocID, LAST_VALUE(CASE WHEN LevelNum = 1 THEN DocID ELSE NULL END) OVER ( PARTITION BY BatchID ORDER BY PosInBatch ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW IGNORE NULLS -- 跳过NULL值,直接取最近的非NULL父ID ) AS TargetParentKey FROM #TEMPBATCH ) UPDATE t SET t.ParentKey = bpl.TargetParentKey FROM #TEMPBATCH t JOIN BatchParentLookup bpl ON t.DocID = bpl.DocID WHERE t.LevelNum = 0 AND t.ParentKey = 0;
验证步骤
执行更新前,可以先查询CTE的结果验证计算是否正确:
WITH BatchParentLookup AS ( SELECT DocID, BatchID, PosInBatch, LevelNum, ParentKey, MAX(CASE WHEN LevelNum = 1 THEN DocID ELSE NULL END) OVER ( PARTITION BY BatchID ORDER BY PosInBatch ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS TargetParentKey FROM #TEMPBATCH ) SELECT * FROM BatchParentLookup ORDER BY BatchID, PosInBatch;
注意:如果某批次开头就是LevelNum=0的行(无前置父行),
TargetParentKey会返回NULL,可根据业务需求添加额外逻辑处理这类场景。
内容的提问来源于stack exchange,提问作者user23264892
相关产品推荐
相关产品推荐

