获取oracle两个时间断的月份与天数

1.2017-01-05至2018-04-05 希望返回 每个月有几天,可以用一个函数或者存储过程来实现

2.因为有大量的数据需要处理,所以返回值需要有对应,也就是说输入(id,起始日期,结束日期) 就可以返回对应的id 每个月的天数: id 月份 天数

函数设计思路

 --计算相差月份
循环{
            --赋值当前日期(累加)
            --计算当前年是否闰年
            --追加当前年月和天数
            --当前日期加1
}

函数内容

 create or replace function GETMONTHANDDAYS(ID VARCHAR2,DATE_START in DATE, DATE_END in DATE) return varchar2 is
  FunctionResult varchar2(2000) := '';
  type num_list is varray(12) of VARCHAR2(2);
  P_DAYS num_list := num_list('31','30','31','30','31','30','31','31','30','31','30','31');
  P_DAYS_RUNNIAN num_list := num_list('31','29','31','30','31','30','31','31','30','31','30','31');
  CUR_DATE DATE;
  CUR_YEAR NUMBER;
  CUR_MONTH NUMBER;
  GE_MONTH NUMBER;

begin
  select ceil(months_between(DATE_END,DATE_START)) INTO GE_MONTH FROM DUAL;
  CUR_DATE := DATE_START;
  if GE_MONTH>0 then
    LOOP
      EXIT WHEN GE_MONTH=0;
      select extract(year from CUR_DATE) into CUR_YEAR FROM DUAL;
      SELECT EXTRACT(MONTH FROM CUR_DATE) INTO CUR_MONTH FROM DUAL;
      IF ((mod(CUR_YEAR, 4)=0 and mod(CUR_YEAR, 100)!= 0) or  (mod(CUR_YEAR, 400) = 0)) then
        FunctionResult := (FunctionResult||';'||ID||','||to_char(CUR_DATE,'yyyymm')||','||P_DAYS_RUNNIAN(CUR_MONTH));
      ELSE 
        FunctionResult := (FunctionResult||';'||ID||','||to_char(CUR_DATE,'yyyymm')||','||P_DAYS(CUR_MONTH));
      END IF;
      CUR_DATE:= ADD_MONTHS(CUR_DATE,1);
      GE_MONTH := GE_MONTH - 1;
    END LOOP;
  end if;
  return(substr(FunctionResult,2));
end GETMONTHANDDAYS;

结果示例(只需要根据分号截取每一条看是不是你想要的)
图片说明

可以让显示按行来显示吗?或者插入一个表中有三列,id 月份 天数?

select trunc(时间1- 时间2) from table_name;

我才发现,不对啊 2017-01-05至2018-04-05 这个日期得2017-01天数应该是27 2018-04 的颖是5天,怎么出来都是31和30天???

IF ((mod(CUR_YEAR, 4)=0 and mod(CUR_YEAR, 100)!= 0) or (mod(CUR_YEAR, 400) = 0)) then
IF (EXTRACT(month FROM CUR_DATE)==EXTRACT(month FROM DATE_START)) then
FunctionResult := (FunctionResult||';'||ID||','||to_char(CUR_DATE,'yyyymm')||','||(P_DAYS_RUNNIAN(CUR_MONTH)-EXTRACT(day FROM DATE_START));
ELSE
FunctionResult := (FunctionResult||';'||ID||','||to_char(CUR_DATE,'yyyymm')||','||P_DAYS_RUNNIAN(CUR_MONTH));
END IF
ELSE

IF (EXTRACT(month FROM CUR_DATE)==EXTRACT(month FROM DATE_END)) then
FunctionResult := (FunctionResult||';'||ID||','||to_char(CUR_DATE,'yyyymm')||','||EXTRACT(day FROM DATE_END));
ELSE
FunctionResult := (FunctionResult||';'||ID||','||to_char(CUR_DATE,'yyyymm')||','||P_DAYS(CUR_MONTH));
END IF
END IF;
--中间那一段改成这个试试