每个月分别在两个日期之间找出天数差异的最简单方法是什么。
假设我有两个日期
2016年5月1日至5日
2016年6月2日至8日
我想要获得的结果是五月的天数和六月的天数(201605-6,201606-8)。
哪种方法最好?
答案 0 :(得分:0)
在您的情况下,Number
和start_date
位于表格的同一行中,因此一个解决方案是:
创意:使用2 输入创建功能:end_date
和start_date
,输出:{{1 }}
练习:首先,创建一个函数end_date
,返回每个string_with_days_in_each_month_between_two_date
和GET_DAYS_EACH_MONTH_BETWEEN
start_date
其次,将您的功能应用于end_date
CREATE OR REPLACE FUNCTION GET_DAYS_EACH_MONTH_BETWEEN
(start_date IN date, end_date IN date)
RETURN varchar2 IS
result varchar2(4000);
BEGIN
WITH tmp AS
(SELECT
LAST_DAY(ADD_MONTHS( start_date, level-1 ))
FROM
(SELECT
start_date
,end_date
FROM
dual)
CONNECT BY
level <= MONTHS_BETWEEN(
TRUNC(end_date,'MM'),
TRUNC(start_date,'MM') )
)
, tmp1 AS
(
SELECT start_date date_col FROM dual
UNION ALL
SELECT end_date from dual
UNION ALL
SELECT * FROM tmp
)
SELECT
LISTAGG(result_col, ',') WITHIN GROUP (ORDER BY date_col) into result
FROM
(SELECT
TO_CHAR(date_col,'yyyyMM') || '_' || TO_CHAR(date_col - LAG(date_col) OVER (ORDER BY date_col)) result_col
, date_col
,ROW_NUMBER() OVER (ORDER BY date_col) rwn
FROM
tmp1
ORDER BY
date_col
)
WHERE
rwn <> 1;
RETURN result;
END;
结果:
your table
重要提示:结果字符串的长度只有4000个字符,因此您应该考虑WITH test_table AS
(
SELECT
TO_DATE('2016-02-06','yyyy-mm-dd') start_date
,TO_DATE('2016-06-08','yyyy-mm-dd') end_date
FROM
DUAL
UNION ALL
SELECT
TO_DATE('2016-05-06','yyyy-mm-dd')
,TO_DATE('2016-06-08','yyyy-mm-dd')
FROM
DUAL
)
SELECT
start_date, end_date
,GET_DAYS_EACH_MONTH_BETWEEN(start_date, end_date) result_col
FROM
test_table;
和start_date end_date result_col
2/6/2016 6/8/2016 201602_23,201603_31,201604_30,201605_31,201606_8
5/6/2016 6/8/2016 201605_25,201606_8
距离每个
该功能使用this link的建议结果来确定2个给定日期之间的所有月份。
答案 1 :(得分:0)
我做了一个递归方法:
with recur (dias, texto, nivel, d1,d2) as
(select last_day(d1)-d1 as dias, to_char(d1,'yyyymm')||'-' as texto, 0 as nivel, d1,d2 from dates union all --first date
select case when (d2-trunc(add_months(d1, nivel+1),'month')+1) > extract(day from last_day(add_months(d1, nivel+1)))
then extract(day from last_day(add_months(d1, nivel+1)))
else d2-trunc(add_months(d1, nivel+1),'month')+1 end as dias,
to_char(add_months(d1, nivel+1),'yyyymm')||'-' as texto, nivel+1 as nivel ,d1,d2 from recur where trunc(add_months(d1, nivel+1),'month') < d2 --last month
)
select d1, d2,listagg(texto||to_char(dias),',') within group (order by nivel) as resultado
from recur
group by d1,d2
order by d1,d2;
2016年5月25日至2016年6月8日的输出
25-MAY-16 08-JUN-16 201605-6,201606-8
2016年5月25日至2017年7月8日的输出
25-MAY-16 08-JUL-17 201605-6,201606-30,201607-31,201608-31,201609-30,201610-31,201611-30,201612-31,201701-31,201702-28,201703-31,201704-30,201705-31,201706-30,201707-8