Oracle 10g:为含EID字段的表补全缺失日期并复制EID
为带EID字段的表补全缺失月份(复制对应EID)
针对你现在包含EID、DT、FLAG字段的表补全需求,我们需要调整之前的存储过程,核心是为每个EID单独生成其时间范围内的所有月份,再和原表做差集插入缺失行,同时保留对应EID并将缺失行的FLAG设为V。
原表示例(输入)
| EID | DT | FLAG |
|---|---|---|
| 123 | 2015-MAY | E |
| 123 | 2015-JUN | H |
| 123 | 2015-OCT | E |
| 123 | 2016-FEB | E |
期望结果(输出)
| EID | DT | FLAG |
|---|---|---|
| 123 | 2015-MAY | E |
| 123 | 2015-JUN | H |
| 123 | 2015-JUL | V |
| 123 | 2015-AUG | V |
| 123 | 2015-SEP | V |
| 123 | 2015-OCT | E |
| 123 | 2015-NOV | V |
| 123 | 2015-DEC | V |
| 123 | 2016-JAN | V |
| 123 | 2016-FEB | E |
实现存储过程
下面的存储过程会动态获取每个EID的最小和最大DT,为每个EID生成该区间内的所有月份,再插入原表中不存在的行:
CREATE OR REPLACE PROCEDURE FILL_DATE_GAP_WITH_EID AS BEGIN -- 插入每个EID缺失的月份行,FLAG设为V INSERT INTO YOUR_TABLE_NAME (EID, DT, FLAG) SELECT e.EID, TO_CHAR(ADD_MONTHS(e.min_dt, LEVEL - 1), 'yyyy-MON') AS DT, 'V' AS FLAG FROM ( -- 获取每个EID的最小和最大日期(统一格式为每月第一天) SELECT EID, MIN(TRUNC(TO_DATE(DT, 'yyyy-mon'), 'MM')) AS min_dt, MAX(TRUNC(TO_DATE(DT, 'yyyy-mon'), 'MM')) AS max_dt FROM YOUR_TABLE_NAME GROUP BY EID ) e CONNECT BY LEVEL <= MONTHS_BETWEEN(e.max_dt, e.min_dt) + 1 AND PRIOR e.EID = e.EID AND PRIOR SYS_GUID() IS NOT NULL -- 避免循环引用 MINUS -- 排除原表已存在的行 SELECT EID, DT, FLAG FROM YOUR_TABLE_NAME; END FILL_DATE_GAP_WITH_EID; /
关键说明
- 动态时间范围:通过子查询获取每个EID的最小和最大
DT,确保只生成该EID需要补全的月份区间,适配不同EID的时间范围差异。 - 连续月份生成:结合
CONNECT BY和ADD_MONTHS,为每个EID生成从最小到最大日期之间的所有月份。 - 去重插入:用
MINUS排除原表中已有的EID+DT组合,只插入真正缺失的行,避免重复数据。 - 日期格式统一:用
TRUNC(TO_DATE(DT, 'yyyy-mon'), 'MM')将原表日期转换为每月第一天,再用TO_CHAR转回yyyy-MON格式,确保和原表日期格式一致。
注意:记得把代码中的YOUR_TABLE_NAME替换成你实际使用的表名。
内容的提问来源于stack exchange,提问作者Hey StackExchange
相关产品推荐
相关产品推荐

