在sql中找工作日

时间:2014-05-31 18:09:46

标签: oracle stored-procedures plsql

我有一个表'country_holiday',它有两列country_id和holiday_dt,这个表没有周末的条目。 我需要编写一个过程,它接受3个输入start_dt,end_dt和country_id,然后迭代给定country_id的两个给定日期之间的所有工作日期

我尝试写这样的东西不起作用(我得到一个空白的光标)

create or replace procedure check_data(p_start_date in date, p_end_date in date, p_country_id in number)
IS
curr_date date;
CURSOR v_buss_days is select p_start_date + rownum -1
from all_objects where rownum <= p_end_date - p_start_date +1
and to_char(p_start_date+rownum-1,'DY') not in ('SAT','SUN')
and p_start_date + rownum -1 not in (select holiday_dt from country_holiday where country_id = p_country_id)

BEGIN
 for curr_date in v_buss_days
LOOP
dbms_output.put_line(curr_date)
END LOOP;
END

我尝试运行查询

select p_start_date + rownum -1
from all_objects where rownum <= p_end_date - p_start_date +1
and to_char(p_start_date+rownum-1,'DY') not in ('SAT','SUN')

这给了我0行p_start_date = '01 dec 2013'和p_end_date = '31 dec 2013',似乎我的填充光标的查询不正确。

正确填充光标后面临问题

感谢您的帮助,确实有效....但是当我尝试在程序中使用时面临问题......

create or replace procedure check_data(p_start_date in date, p_end_date in date, p_cntry_id in number)
IS
curr_num_of_empoyee number;
curr_date date;
CURSOR v_buss_days is select work_date from
( with dates  as 
   ( select p_start_date dt_start, p_end_date dt_end    from dual  )
  select dt_start + (level-1) work_date from dates
  connect by level <= (dt_end - dt_start + 1 )
  ) wdates
where work_date not in ( select HOLIDAY_DATE 
                        from country_holiday
                        where country_id = p_cntry_id)
and to_char(work_date,'DY') not in ('SAT','SUN')
order by work_date;
BEGIN
for curr_date in v_buss_days
LOOP
select count(*)  into curr_num_of_empoyee from employee_details where country_id = p_cntry_id and data_dt = curr_date;
END LOOP;
END;

错误是 19/101 PLS-00382:表达式类型错误

似乎问题部分是“data_dt = curr_date”

1 个答案:

答案 0 :(得分:2)

以下是我在SQLFiddle上提出的问题。删除WITH子句并替换为过程日期参数。您可以使用CONNECT BY和LEVEL的组合生成一组具有递增数值的行。然后,将其添加到您的开始日期,并从您的假期表和周末过滤掉。

select work_date from
(
   with dates  as 
   ( select to_date('01/01/2014','MM/DD/YYYY') dt_start,
     to_date('01/10/2014','MM/DD/YYYY') dt_end
     from dual
   )
  select dt_start + (level-1) work_date
  from dates
  connect by level <= (dt_end - dt_start + 1 )
  ) wdates
where work_date not in ( select holiday_dt 
                        from country_holiday
                        where country_id = 1)
and to_char(work_date,'DY') not in ('SAT','SUN')
order by work_date