在 plsql 中计算两个日期之间的星期日:date1 和 :date2

count Sunday in plsql between two dates :date1 and :date2

我知道论坛上有很多这方面的工作,但我尝试了很多东西但出现错误请问我在 oracle 报告中有两个参数:date1 和 :date2 我想检查星期日然后 return 给出我这两个日期有多少个星期天

function SUNDAY_CFormula return NUMBER is
start_date DATE := :DATE1;
end_date DATE := :DATE2;
A NUMBER;
begin
SELECT Count(*) 
FROM   (SELECT To_char(start_date + ( LEVEL - 1 ), 'fmday')INTO A 
        FROM DUAL;   
        CONNECT BY LEVEL <= end_date - start_date + 1) 
WHERE  A IN ( 'sunday' );
RETURN A;
end;

您可以像下面这样重写您的函数。在 to_char 函数中添加 'nls_date_language = english' 子句更安全,以使您的函数独立于默认环境设置。

create or replace 
function SUNDAY_CFormula (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(start_date + ( LEVEL - 1 ), 'fmday', 'nls_date_language = english') A
        FROM DUAL 
        CONNECT BY LEVEL <= end_date - start_date + 1
        ) t
WHERE  t.A IN ( 'sunday' );
RETURN A;
end;
/

您甚至可以使用以下版本使您的函数在将两个日期作为参数时更加灵活,无论 date1 大于还是小于 date2。

create or replace 
function SUNDAY_CFormula (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(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;
/

作为替代方案。我总是尝试为日期 运行ge 过程创建公式而不是“迭代”,我只是不喜欢生成数据就把它扔掉。是的,有时是必要的,但在这种情况下不是。以下将完成您想要的:

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的逻辑似乎完全没有问题。那时我只需要知道为什么。花了一段时间,但 her/his 代码中有一个小错误。事实证明,当开始日期大于结束日期时,他们的例行程序实际上开始寻找最伟大日期的日期并向前推进。因此,更改期间查看该日期中较大的日期加上天数。这是通过将最小函数应用于“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;