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

Posted

技术标签:

【中文标题】在两个日期之间计算 plsql 中的星期日:date1 和:date2【英文标题】:count Sunday in plsql between two dates :date1 and :date2 【发布时间】:2021-02-26 10:31:16 【问题描述】:

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

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;

【问题讨论】:

【参考方案1】:

你可以像下面这样重写你的函数。在 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;
/

【讨论】:

【参考方案2】:

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

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;

【讨论】:

以上是关于在两个日期之间计算 plsql 中的星期日:date1 和:date2的主要内容,如果未能解决你的问题,请参考以下文章

SQL语句计算两个日期之间有多少个工作日的方法

如何计算 Postgres 中两个日期之间除星期日以外的天数?

如何删除两个日期之间的星期六和星期日并计算总天数[重复]

计算两个特定日期之间有多少个星期五(或任何一个)?

怎么取两个日期之间的周数

c#如何计算两个日期之间相隔天数