作为替代。我总是尝试为日期范围过程创建公式,而不是“迭代”,我只是不喜欢生成数据只是把它扔掉。是的,有时这是必要的,但在这种情况下不是。以下将完成您想要的:
create or replace
function sunday_calc ( date1_in date
, date2_in date
, sun_in varchar2 default 'sun'
)
return number
is
sun_count integer;
begin
with date_range( start_date, end_date) as
( select trunc(least(date1_in,date2_in))
, trunc(greatest(date1_in,date2_in))
from dual
)
select floor((trunc(end_date) - trunc(next_day(start_date-1,sun_in))/7)) + 1
into sun_count
from date_range;
return sun_count;
end sunday_calc;
注意:不幸的是 next_day 函数不接受 NLS_DATE_LANGUAGE 参数,所以我创建了一个替代。 sun_in 参数:包含对应英文日'Sunday'的目标语言名称
与@MDO 的函数相比,我对此感到好奇,我对每个函数都进行了一些测试。他们产生了同样的结果; 除了在某些情况下,开始日期大于结束日期,相差 1。与实际日历相比,公式是正确的 (see fiddle)。但是为什么,MDO 的逻辑似乎完全合理。那时我只需要知道为什么。花了一段时间,但她/他的代码中有一个小错误。事实证明,当开始日期大于结束日期时,他们的例程实际上开始查看最大日期的日期并向前推进。因此,更改期间查看到该日期的日期加上天数中的较大者。这可以通过将最小函数应用于“Select to_char(start_date...”) 来纠正,结果是:
create or replace
function sunday_cformula_r (date1 date, date2 date) return number is
start_date date := date1;
end_date date := date2;
a number;
begin
select count(*) into a
from (select to_char(least(end_date, start_date) + ( level - 1 ), 'fmday', 'nls_date_language = english') a
from dual
connect by level <= greatest(end_date, start_date) - least(end_date, start_date) + 1
) t
where t.a in ( 'sunday' );
return a;
end;