我有三张桌子: -
per_Absences_table有start_date,end_date。 per_absence_type有Privelege,Casual等 per_people_table有员工编号,员工姓名
我想知道员工在两个日期之间申请的离职数量。
例如: - 如果我将'1-JAN-2013'作为开始日期,'20 -JUN-2013'作为结束日期,那么该员工应用的所有叶子 将作为输出
我已经编写了代码,当我传递任何参数时它正在工作。但是假设有一名员工申请休假 从2013年5月10日到2013年5月20日,我将开始日期定为2013年5月11日,即2013年5月11日之后休假的员工应该来。
即。应出现2013年5月10日至2013年5月20日的假期。此外,如果我想找到已经申请休假的员工,直到2103年5月19日
然后应该出现这个假期。所有其他案件都得到了照顾。
per_people_table: -
EMP_NUM EMP_NAME
P101 XYZ
PER_ABSENCE_TABLE
EMP_NUM START_DATE END_DATE TYPE_ID
101 10-May-2013 15-May-2013 1
per_absence_type
type_id leave_type
1 casual
现在,如果我将参数传递给2013年5月11日(p_start_date),那么这条记录应该会出现。
如果我在2013年5月19日(实际结束日期之前)传递参数,那么即使这个记录也会出现。
即
declare
l_r varchar2(10) :=NULL;
L_E VARCHAR2(10) := NULL;
p_person_id VARCHAR2(10) :='P101',
p_start_date VARCHAR2(10);
p_end_date VARCHAR2(10);
leave_type VARCHAR2(10);
BEGIN
Leave_detail_packa.Leave_detail_packA(NULL,NULL,'P101','11-MAY-2013',NULL,NULL);
END;
Leave_detail_packa body
procedure Leave_details( errbuff out varchar2,
retcode out varchar2,
p_person_id VARCHAR2,
p_start_date varchar2,
p_end_date varchar2,
leave_type varchar2
)
as
l_st_date :=to_date(trunc(fnd_conc_date.string_to_date(p_start_date)));
l_end_date :=to_date(trunc(fnd_conc_date.string_to_date(p_end_date)));
/****************Cursor for start date ****************************/
Cursor c_var_st_date
is select
to_char(paa.date_start,'DD-MON-RRRR') Start_date
from per_Absences_table paa,
per_absence_type paat
where ( nvl(l_st_date,paa.date_start) between paa.date_start and paa.date_end
or paa.date_start >= nvl(l_st_date,paa.date_start))
paa.type_id =paat.type_id
and paat.name = nvl(leave_type,paat.name);
/****************Cursor for end date ****************************/
Cursor c_var_nd_date
is select
to_char(paa.date_end,'DD-MON-RRRR') End_date
from per_Absences_table paa,
per_absence_type paat
where ( nvl(l_st_date,paa.date_end) between paa.date_start and paa.date_end
or paa.date_end <= nvl(l_st_date,paa.date_end))
paa.type_id =paat.type_id
and paat.name = nvl(leave_type,paat.name);
/********** Cursor to give all the leave details ***************/
Cursor c_var(l_start_date varchar2,
l_end_date1 varchar2)
is
select
emp_number employee_number,
emp_name employee_name,
leave_type Leave_type,
to_char(paa.date_end,'DD-MON-RRRR') End_date,
to_char(paa.date_start,'DD-MON-RRRR') Start_date,
sum(No_of_days) Leave_days
from
per_Absences_table paa,
per_absence_type paat,
per_people_table
where
paa.date_start>= ( nvl(l_start_date),to_char(paa.date_start,'DD-MON-RRRR'))
and paa.date_end <= ( nvl(l_end_date1),to_char(paa.date_end,'DD-MON-RRRR'))
AND EMP_NUM=P_PERSON_ID;
/**** Begin looping******************************************************/
for ( c_var_number in c_var_st_date)
loop
for ( c_var_number1 in c_var_nd_date)
loop
for ( c_var_number3 in c_var(c_var_st_date.start_end,c_var_nd_date.end_date)
loop
dbms.output_put.line( c_var_number3.end_date,c_var_number3.start_date);
end loop;
end loop;
end loop;
答案 0 :(得分:2)
首先,根本不需要使用PL / SQL来完成此操作。它可以在单个SQL语句中完成。
其次,你没有为你的表提供DDL,所以我假设他们按照以下方式设置我们(在SQL Fiddle中还有其他情况):
create table per_people (
emp_num number not null
, emp_name varchar2(100) not null
, constraint pk_per_people primary key (emp_num)
);
create table per_absence_type (
type_id number not null
, leave_type varchar2(100) not null
, constraint pk_absence_type primary key (type_id)
);
create table per_absence (
emp_num number not null
, start_date date not null
, end_date date not null
, type_id number not null
, constraint pk_per_abs primary key (emp_num, start_date)
, constraint fk_per_abs_emp foreign key (emp_num)
references per_people(emp_num)
, constraint fk_per_abs_typ foreign key (type_id)
references per_absence_type (type_id)
, constraint chk_per_abs_dates check (start_date <= end_date )
);
这些是我对这些表的最小限制。如果你错过其中一个,我建议你添加它。
此查询将为您提供所有缺席表中所有信息的所有信息:
select pp.emp_num
, pp.emp_name
, pa.start_date
, pa.end_date
, pat.leave_type
from per_people pp
join per_absence pa
on pp.emp_num = pa.emp_num
join per_absence_type pat
on pa.type_id = pat.type_id
您希望找到所有将在两个日期之间休假的员工。为此,您需要在上面的查询中添加WHERE子句。让我们假设员工有以下缺席:
insert all
into per_absence values( 101, date '2013-05-10', date '2013-05-15', 1)
into per_absence values( 101, date '2013-09-10', date '2013-09-10', 1)
into per_absence values( 102, date '2013-05-15', date '2013-05-20', 1)
into per_absence values( 103, date '2013-05-05', date '2013-05-20', 1)
select * from dual;
如果您通过了2013-05-15的开始日期和2013-05-20的结束日期,则可能会返回三行。如果您通过了2013-05-16的开始日期,那么您只需要两个。
您必须查看如何构造WHERE子句。查看 开始日期所在的日期是在缺席开始日期和结束日期或之间,您的结束日期介于缺席开始日期和结束日期之间。不要忘记缺席只能是一天,所以你想在比较中包括开始和结束日期。
这会将查询更改为:
select pp.emp_num
, pp.emp_name
, pa.start_date
, pa.end_date
, pat.leave_type
from per_people pp
join per_absence pa
on pp.emp_num = pa.emp_num
join per_absence_type pat
on pa.type_id = pat.type_id
where ( :start_date between pa.start_date and pa.end_date
or :end_date between pa.start_date and pa.end_date
)
现在,您想要查找给定日期之间特定员工的假期数。由于您的表格已正确规范化,您可以通过EMP_NUM GROUP BY为每位员工获取该表格。
假设您在2013-05-15和2013-05-20之间想要EMP_NUM 1(单个员工,因此不需要GROUP BY),则查询将如下所示:
select count(*) as no_leaves
from per_people pp
join per_absence pa
on pp.emp_num = pa.emp_num
join per_absence_type pat
on pa.type_id = pat.type_id
where emp_num = 101
and ( date '2013-05-15' between pa.start_date and pa.end_date
or date '2013-05-20' between pa.start_date and pa.end_date
)
答案 1 :(得分:0)
如果我遇到这个问题,我会创建一个日历表,使用BETWEEN paa.date_start AND paa.date_end
加入;这样,无论他们什么时候开始或结束,我都知道他们是否在任何一天休假。如果从那里你有兴趣了解他们花了多少叶子,将连续几天定义为休假的例子,那么你只需要在休假日之间找到差距。