如何将SAS循环逻辑转换为SQL Server查询生成ETUDE1表
需求说明
需将原有SAS代码逻辑转换为SQL Server查询,从ETUDE表生成ETUDE1表,核心规则如下:
- 当
TYP_RTE='V'时,为原表每行生成从AGE_FIN_REDR到AGE_DEB递减的新增列A - 当
TYP_RTE='T'时,为原表每行生成从AGE_FIN_REDR+1到AGE_DEB递减的新增列A
原表ETUDE共1814行,目标表ETUDE1需生成139427行。
SQL Server实现方案
方案1:适用于SQL Server 2022及以上版本(推荐)
利用SQL Server 2022新增的GENERATE_SERIES函数直接生成递减序列,语法简洁高效:
-- 直接生成ETUDE1表 SELECT e.*, s.value AS A INTO ETUDE1 FROM ETUDE e CROSS APPLY ( -- 根据TYP_RTE确定序列起始值,步长-1实现递减 SELECT value FROM GENERATE_SERIES( CASE WHEN e.TYP_RTE = 'V' THEN e.AGE_FIN_REDR ELSE e.AGE_FIN_REDR + 1 END, e.AGE_DEB, -1 ) ) s -- 过滤起始值小于结束值的行,避免生成空序列 WHERE CASE WHEN e.TYP_RTE = 'V' THEN e.AGE_FIN_REDR ELSE e.AGE_FIN_REDR + 1 END >= e.AGE_DEB;
方案2:适用于SQL Server 2019及以下版本
通过递归CTE生成数字序列,再与原表关联实现需求:
-- 递归CTE生成覆盖所有可能范围的数字序列 WITH NumberSeries AS ( SELECT MAX(CASE WHEN TYP_RTE = 'V' THEN AGE_FIN_REDR ELSE AGE_FIN_REDR + 1 END) AS num FROM ETUDE UNION ALL SELECT num - 1 FROM NumberSeries WHERE num > (SELECT MIN(AGE_DEB) FROM ETUDE) ) -- 关联原表生成ETUDE1表 SELECT e.*, ns.num AS A INTO ETUDE1 FROM ETUDE e JOIN NumberSeries ns ON ns.num BETWEEN e.AGE_DEB AND CASE WHEN e.TYP_RTE = 'V' THEN e.AGE_FIN_REDR ELSE e.AGE_FIN_REDR + 1 END -- 按原表主键+A列递减排序,确保序列顺序符合要求 ORDER BY e./* 替换为原表主键列名 */, ns.num DESC;
逻辑说明
- 两种方案核心都是为原表每行生成对应范围的递减数字序列,通过
CROSS APPLY或JOIN将原表行与序列行关联,实现一行转多行的效果 - 过滤条件确保仅生成有效序列(起始值≥结束值时才会生成数据)
内容的提问来源于stack exchange,提问作者nadal
相关产品推荐
相关产品推荐

