我希望在这两个日期之间只有工作日。我知道我们对我的问题有很多解决方案,但我正在寻找一些特别适合我的例子的东西
我的 sql 查询有条件
WHERE DATE_FIELD BETWEEN '1-JAN-13' AND '31-MAR-13'
AND (DATE_FIELD1 - DATE_FIELD2) > 10
我希望在两个日期之间只获得工作日,并且我希望在计算 DATE_FIELD1 - DATE_FIELD2 期间,它只考虑工作日,不包括周末。
通过截断到一周的开始日期,可以计算工作日。
确定一周的开始并从日期值中减去它以获得工作日的编号:
date_field2-trunc(date_field2,'D')
之后,可以计算日期之间的工作日数:
select
nvl(sum(
case
when
(
(date_field1 + (level-1))
-
trunc(date_field1 + (level-1),'D')
)
> 4 then 0
else 1
end
),0)
from
dual
start with
date_field2 > date_field1
connect by
level < (date_field2 - date_field1)
并将此值合并到查询中:
with sample_table as (
select
trunc(sysdate) date_field1,
trunc(sysdate) + level - 1 date_field2
from dual
connect by level <= 20
)
select
to_char(date_field1, 'yyyy-mm-dd') date_field1,
to_char(date_field2, 'yyyy-mm-dd') date_field2,
date_field2-trunc(date_field2,'D') date_field2_week_day,
(date_field2 - date_field1) days_between,
(
select
nvl(sum(
case
when
(
(date_field1 + (level-1))
-
trunc(date_field1 + (level-1),'D')
)
> 4 then 0
else 1
end
),0)
from dual
start with date_field2 > date_field1
connect by
level < (date_field2 - date_field1)
)
work_days_between
from
sample_table
where
(
select
nvl(sum(
case
when
(
(date_field1 + (level-1))
-
trunc(date_field1 + (level-1),'D')
)
> 4 then 0
else 1
end
),0)
from dual
start with date_field2 > date_field1
connect by
level < (date_field2 - date_field1)
)
> 10
或制作一个函数以返回相应的天数:
create or replace function get_work_days_between(
pDate1 in date,
pDate2 in date
) return number deterministic parallel_enable
as
vResult number;
vDate1 date;
vDate2 date;
begin
vDate1 := trunc(pDate1);
vDate2 := trunc(pDate2);
select
nvl(sum(
case
when
(
(vDate1 + (level-1))
-
trunc(vDate1 + (level-1),'D')
)
> 4 then 0
else 1
end
),0)
into
vResult
from
dual
start with
vDate2 > vDate1
connect by
level < (vDate2 - vDate1)
;
return vResult;
end;
并在查询中使用它:
with sample_table as (
select
trunc(sysdate) date_field1,
trunc(sysdate) + level - 1 date_field2
from dual
connect by level <= 20
)
select
to_char(date_field1, 'yyyy-mm-dd') date_field1,
to_char(date_field2, 'yyyy-mm-dd') date_field2,
date_field2-trunc(date_field2,'D') date_field2_week_day,
(date_field2 - date_field1) days_between,
get_work_days_between(date_field1, date_field2) work_days_between
from
sample_table
where
get_work_days_between(date_field1, date_field2) > 10
;
WITH dates AS
(
SELECT (TO_DATE('01-JAN-13', 'DD-MON-YY') - 1) + LEVEL AS d_date
, TO_CHAR((TO_DATE('01-JAN-13', 'DD-MON-YY') - 1) + LEVEL, 'D') AS d_day_no
FROM DUAL
CONNECT BY
LEVEL < ABS(TO_DATE('01-JAN-13', 'DD-MON-YY') - TO_DATE('31-MAR-13', 'DD-MON-YY')) + 2
)
SELECT *
FROM A_TABLE
WHERE DATE_FIELD IN -- Instead of: WHERE DATE_FIELD BETWEEN '1-JAN-13' AND '31-MAR-13'
(
SELECT d_date
FROM dates
WHERE d_day_no NOT IN (6, 7) -- Skip: Sat and Sun
)
AND (DATE_FIELD1 - DATE_FIELD2) > 10
;