计算表中每行的两个日期之间的工作日

时间:2014-02-04 12:35:20

标签: sql oracle

我正在尝试实施this askTom solution来统计表格中两个日期字段之间的工作日。

 select count(*)
   from ( select rownum rnum
            from all_objects
           where rownum <= to_date('&1') - to_date('&2')+1 )
  where to_char( to_date('&2')+rnum-1, 'DY' ) not in ( 'SAT', 'SUN' )

我不知道如何将值传递给toms代码或如何进行解决方案,以便每次select使用不同的日期集执行时都会获得类似的输出:

rowid | bussiness_days

我想这可以通过PL / SQL块来实现,但如果可能的话,我更愿意将其保留为查询。是否可以使用&amp; 1参数从选择上面的一个参数传递值?

3 个答案:

答案 0 :(得分:2)

这与原来的askTom不同,但如果你使用的是11gR2,你可以使用递归CTE:

with rcte(a,b, i, is_wd) as (
select from_dt , to_dt , id, case when (to_char(from_dt, 'DY') in ('SAT','SUN')) then 0 else 1 end from t
  union all
  select decode(a, null, a,a+1), b, i, case when (to_char(a, 'DY') in ('SAT','SUN')) then 0 else 1 end 
  from rcte
  where a+1 <= b
)
select i id, sum(is_wd) 
from rcte
group by i

其中t是包含“from_dates”和“to_dates”

的表

Here is a sqlfiddle demo

答案 1 :(得分:1)

试试这个:

SELECT COUNT(*)
   FROM ( SELECT ROWNUM rnum
            FROM all_objects
           WHERE ROWNUM <= TO_DATE('2014-02-07','yyyy-mm-dd') - TO_DATE('2014-02-01','yyyy-mm-dd')+1 )
  WHERE TO_CHAR( TO_DATE('2014-02-01','yyyy-mm-dd')+rnum-1, 'DY' ) NOT IN ( 'SAT', 'SUN' )

然而,它至少有两个问题:

  • 假设会话NLS_DATE_LANGUAGE设置为英语
  • 如果ALL_OBJECTS中的行数小于范围之间的天数,则查询会给出错误的结果。

该版本不易出错且速度更快:

WITH t AS   
    (SELECT TO_DATE('2014-02-01','yyyy-mm-dd')+LEVEL-1 the_date 
    FROM dual
    CONNECT BY TO_DATE('2014-02-01','yyyy-mm-dd')+LEVEL-1 <= TO_DATE('2014-02-07','yyyy-mm-dd'))
SELECT COUNT(*)
FROM t
WHERE TO_CHAR(the_date, 'DY', 'NLS_DATE_LANGUAGE = AMERICAN') NOT IN ( 'SAT', 'SUN' )

答案 2 :(得分:0)

这是另一种日历表派上用场的情况。日历表的每个日期都有一行。

如果星期六和星期日不是工作日,很可能假期也不是。日历表中用于指示假期的字段使得从工作日计算中排除它们变得容易得多。