SQL Server 日期范围按每月一行拆分

列如这样开始日期 '2021-04-23'结束日期为'2021-05-25'输出结果为下图,但是如果是同月就不变

img

这里要用到递归写法,刚好之前有写过oracle的这个需求


create table temp_datetest (fromdate date,todate date);
insert into temp_datetest values (DATE '2019-06-20',DATE '2019-09-21');
commit;

WITH cte(fromdate,
todate1,
todate,
lev) as
 (select fromdate, last_day(fromdate) todate1, todate, 1 as lev
    from temp_datetest
  union all
  select add_months(trunc(fromdate, 'mm'), 1),
         least(add_months(last_day(fromdate), 1), todate),
         todate,
         lev + 1
    from cte
   where lev < months_between(last_day(todate), trunc(fromdate, 'mm')) + 2)
select FROMDATE, TODATE1 from cte;

img

在sqlserver 中也可以使用with进行递归,语法基本和oracle一致,但是日期计算函数和oracle中不一样,需要你自行替换成sqlserver中的函数,比如取月第一天、月最后一天、两个日期间间隔的月份数、指定日期加一月等

如果是对已有数据进行处理,那就多写几个语句来处理,否则还是写触发器或者在程序前端来防止这样的数据产生。
思路:
取from_date和to_data的月份,
如果相同,则将from_date为start_date,to_data为end_date插入结果表
如果不相同,则求from_date和to_data的月份的差值diff,
然后int i=0循环diff次
如果i==0,取from_date为start_date,from_date的当月月底日期为end_date,插入结果表,continue
如果i+1==diff,取to_data的当月第一天为start_date,to_data为end_date,插入结果表,continue
将from_date的月份加+1,得到下一个月的时间next,取next的当月第一天为start_date,取next的当月月底日期为end_date,插入结果表