我的查询有点像这样:
select 1 from dual where :p1_task_date in (sysdate,sysdate+1,sysdate-1) and :p1_task_id is not null
这很好用,但我希望得到下一个/上一个工作日(下一个/上周工作日)而不是sysdate + 1和sysdate-1。我试过像:
select next_day(sysdate, to_char(sysdate+1,'DAY')) from dual`
但不能继续这样做:(
请帮助!!!!
答案 0 :(得分:8)
@Tawman的答案会有效,但我更喜欢这种方法的可读性:
select sysdate as current_date,
case when to_char(sysdate,'D') in (1,6,7)
then next_day(sysdate,'Monday')
else sysdate+1 end as next_weekday,
case when to_char(sysdate,'D') in (1,2,7)
then next_day(sysdate-7,'Friday')
else sysdate-1 end as prev_weekday
from dual
正如其他人所说,这只会排除周末,而不是假期。
答案 1 :(得分:5)
不考虑假期,您可以使用DECODE函数使用星期几来执行一些简单的日期数学运算:
SELECT SYSDATE-DECODE(TO_CHAR(SYSDATE, 'D'), 2, 3, 1, 2, 1) AS WORK_DATE_BEFORE,
TO_CHAR(SYSDATE-DECODE(TO_CHAR(SYSDATE, 'D'), 2, 3, 1, 2, 1), 'DAY') AS WORK_DAY_BEFORE,
SYSDATE AS BASE_DATE,
TO_CHAR(SYSDATE, 'DAY') AS BASE_DAY,
SYSDATE+DECODE(TO_CHAR(SYSDATE, 'D'), 6, 3, 7, 2, 1) AS WORK_DATE_AFTER,
TO_CHAR(SYSDATE+DECODE(TO_CHAR(SYSDATE, 'D'), 6, 3, 7, 2, 1), 'DAY') AS WORK_DAY_AFTER
FROM DUAL
只需用包含要检查日期的变量替换SYSDATE即可。 DECODE使用星期几来确定从基准日期添加或减去的天数。
答案 2 :(得分:2)
要根据区域设置进行星期几的日期计算,您可以truncation使用beginning of ISO week always a Monday SQL Fiddle test。
上一个工作日:
(
case
when (date_value - trunc(date_value,'IW')) in (5,6,0)
then trunc(date_value-1,'IW') + 4
else date_value - 1
end
) prev_working_day
下一个工作日:
(
case
when (date_value - trunc(date_value,'IW')) in (4,5,6)
then trunc(date_value+3,'IW')
else date_value + 1
end
) next_working_day
以下是完整的示例代码。
<强> {{3}} 强>
with date_set as (
select
(trunc(sysdate) - 7 + level) as date_value
from dual
connect by level <= 14
),
calculated_days as (
select
date_value,
(
case
when (date_value - trunc(date_value,'IW')) in (5,6,0)
then trunc(date_value-1,'IW') + 4
else date_value - 1
end
) prev_working_day,
(
case
when (date_value - trunc(date_value,'IW')) in (4,5,6)
then trunc(date_value+3,'IW')
else date_value + 1
end
) next_working_day
from
date_set
)
select
date_value,
to_char(date_value,'DAY') date_week_day,
prev_working_day,
to_char(prev_working_day,'DAY') prev_day_week_day,
next_working_day,
to_char(next_working_day,'DAY') next_day_week_day
from calculated_days
答案 3 :(得分:1)
我认为最好的方法是使用dbms_scheduler创建所有工作日的计划。这样你可以根据需要调整它,你的代码永远不必改变。创建计划后,使用dbms_scheduler.evaluate_calendar_string函数计算下一个日期。这将在周一至周五进行,但您可以轻松地改进计划以删除假期:
set serveroutput on
DECLARE
lv_next_work_date DATE;
BEGIN
dbms_scheduler.create_schedule(schedule_name=>'MY_WORKDAY_SCHEDULE',
repeat_interval=>'FREQ=DAILY;BYDAY=MON,TUE,WED,THU,FRI');
dbms_scheduler.evaluate_calendar_string(start_date => trunc(sysdate),
calendar_string => 'MY_WORKDAY_SCHEDULE',
return_date_after => trunc(sysdate),
next_run_date => lv_next_work_date);
dbms_output.put_line(lv_next_work_date);
END;
/
奖金是你也可以用它在工作日自动执行工作。
我刚看到你也希望能够做上一个工作日。这对于时间表来说并不方便,但可以通过快速循环完成。在今天前两天开始,运行计划,看看结果是否在今天之前。如果没有另一天备份再做一次。重复,直到找到上一个工作日。
答案 4 :(得分:0)
此程序允许您将工作日排除在假期和周末之外:
create or replace procedure GetWorkDays(current_day in date default sysdate,
next_date out date,
prev_date out date) is
TYPE HOLIDAY_TYPE IS VARRAY(17) OF varchar(5);
--List all holidays here
holidays HOLIDAY_TYPE := HOLIDAY_TYPE('01.01','02.01','03.01','04.01',
'05.01','06.01','07.01','08.01',
'23.02','08.03','01.05','02.05',
'03.05','09.05','10.05','12.06',
'04.11');
--Internal functions-------------------------------------------------
function IsHoliday(currentDay date) return number is
begin
for i in holidays.first..holidays.last
loop
if to_char(currentDay,'DD.MM') = holidays(i) then return 1;
end if;
end loop;
return 0;
end;
function GetNextWorkDay(currentDay date) return date is
tempDate Date;
begin
tempDate:=currentDay+1;
while IsHoliday(tempDate)=1 loop
tempDate:=tempDate+1;
end loop;
if to_char(tempDate,'D') in (6,7) then
tempDate:=next_day(tempDate,'Monday');
end if;
if IsHoliday(tempDate)=1 then return GetNextWorkDay(tempDate);
else return tempDate;
end if;
end;
function GetPrevWorkDay(currentDay date) return date is
tempDate Date;
begin
tempDate:=currentDay-1;
while IsHoliday(tempDate)=1 loop
tempDate:=tempDate-1;
end loop;
if to_char(tempDate,'D') in (6,7) then
tempDate:=next_day(tempDate-7,'Friday');
end if;
if IsHoliday(tempDate)=1 then return GetPrevWorkDay(tempDate);
else return tempDate;
end if;
end;
------------------------------------------------------------------
begin
next_date:=GetNextWorkDay(current_day);
prev_date:=GetPrevWorkDay(current_day);
end GetWorkDays;
答案 5 :(得分:0)
仅跳过周末:
select
in_date,
case when next_day(in_date,'Monday')>next_day(in_date,'Friday')
then in_date+1 else next_day(in_date,'Monday') end next_w_day,
case when next_day(in_date-8,'Friday')<next_day(in_date-8,'Monday')
then in_date-1 else next_day(in_date-7,'Friday') end previous_w_day
from
(select trunc(sysdate)+rownum in_date from
(select * from all_objects where rownum<15))
order by in_date