SQL Server递归计算列需求:基于种子行递推BOP与EOP列
用递归CTE实现依赖前一行的BOP/EOP计算
没问题,递归CTE(通用表表达式)刚好能解决这种需要基于前一行结果计算当前行的场景!我给你一步一步拆解实现方法,结合你的需求写具体的SQL代码。
核心思路
你的需求里,每一行的BOP等于前一行的EOP,EOP等于前一行EOP加上当前行的IN减去OUT,这完全符合递归查询的逻辑:
- 先定义锚点成员:也就是你的种子行(第一行),计算它的初始
BOP和EOP - 再定义递归成员:通过关联前一行的结果,计算当前行的两个字段
具体SQL示例
假设你的表名为stock_movement,包含排序用的sequence_id(用来保证行的顺序,也可以用日期、时间戳这类字段)、IN、OUT列。下面是适配的代码:
WITH recursive stock_calculation AS ( -- 锚点成员:处理种子行(第一行) SELECT sequence_id, IN, OUT, -- 这里替换成你的种子行初始BOP值,比如如果初始库存是100就写100 0 AS BOP, 0 + IN - OUT AS EOP FROM stock_movement WHERE sequence_id = 1 -- 定位到种子行,也可以用ORDER BY sequence_id LIMIT 1 UNION ALL -- 递归成员:基于前一行计算当前行 SELECT sm.sequence_id, sm.IN, sm.OUT, sc.EOP AS BOP, sc.EOP + sm.IN - sm.OUT AS EOP FROM stock_movement sm JOIN stock_calculation sc ON sm.sequence_id = sc.sequence_id + 1 ) -- 输出最终计算结果 SELECT sequence_id, IN, OUT, BOP, EOP FROM stock_calculation ORDER BY sequence_id;
关键注意事项
- 排序字段必须明确:不管用
sequence_id还是日期,一定要保证每行能准确关联到它的前一行,否则计算结果会乱掉。如果是按日期排序,把关联条件改成sm.transaction_date = sc.transaction_date + INTERVAL '1 day'(根据数据库语法调整)即可。 - 种子行的初始值:如果你的种子行已经有预设的
BOP值,直接把锚点成员里的0换成表中的BOP字段就行,比如SELECT ... BOP, BOP + IN - OUT AS EOP ...。 - 数据库语法适配:不同数据库对递归CTE的语法略有差异,比如MySQL 8.0+需要加
RECURSIVE关键字,SQL Server可以直接用WITH,PostgreSQL支持WITH RECURSIVE,根据你的数据库调整即可。
内容的提问来源于stack exchange,提问作者ArcherBird
相关产品推荐
相关产品推荐

