PL / SQL代码,用于查找员工的详细信息

时间:2013-06-21 17:33:30

标签: sql plsql oracle-sqldeveloper

我有三张桌子: -

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;

2 个答案:

答案 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加入;这样,无论他们什么时候开始或结束,我都知道他们是否在任何一天休假。如果从那里你有兴趣了解他们花了多少叶子,将连续几天定义为休假的例子,那么你只需要在休假日之间找到差距。