Oracle中CASE语句多条件执行问题:生成每月生效合同多行记录
Oracle查询2018年各月初生效的合同(多行结果)
核心思路是先生成2018年所有月份的第一天,再将这些日期与合同表关联,筛选出合同生效区间包含对应月初的记录,这样每个符合条件的月份都会返回一条合同记录,解决CASE语句仅返回首个匹配月份的问题。
方法一:使用CONNECT BY生成日期序列
WITH month_starts AS ( SELECT ADD_MONTHS(DATE '2018-01-01', LEVEL - 1) AS month_start FROM dual CONNECT BY LEVEL <= 12 ) SELECT c.name, ms.month_start FROM contracts c JOIN month_starts ms ON ms.month_start BETWEEN c.date_start AND c.date_end ORDER BY c.name, ms.month_start;
month_starts公共表表达式(CTE)生成2018年1月至12月的每个月第一天。- 通过JOIN关联合同表,筛选出合同生效周期覆盖对应月初的记录,自动生成每个生效月份的对应行。
方法二:使用递归CTE生成日期序列(Oracle 11g+适用)
WITH month_starts(month_start) AS ( SELECT DATE '2018-01-01' FROM dual UNION ALL SELECT ADD_MONTHS(month_start, 1) FROM month_starts WHERE month_start < DATE '2018-12-01' ) SELECT c.name, TO_CHAR(ms.month_start, 'YYYY-MM') AS effective_month, ms.month_start FROM contracts c JOIN month_starts ms ON ms.month_start BETWEEN c.date_start AND c.date_end ORDER BY c.name, ms.month_start;
- 递归CTE逐步生成每个月的第一天,逻辑更直观。
- 可通过
TO_CHAR函数将日期格式化为YYYY-MM样式,直接显示生效年月。
注意事项
- 无论合同的生效起始/结束日期是纯日期还是带时间戳,
BETWEEN判断都能正常生效。 - 若合同在2018年之前开始、之后结束,只要覆盖了2018年的任意月初,都会被筛选出来。
内容的提问来源于stack exchange,提问作者elizabeth
相关产品推荐
相关产品推荐

