【问题标题】:PL/SQL code to find leave detail of employeePL/SQL 代码查找员工的休假详情
【发布时间】:2013-06-18 22:21:55
【问题描述】:

我有三张桌子:-

per_Absences_table 有 start_date、end_date。 per_absence_type 有特权,休闲等 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;

【问题讨论】:

    标签: sql plsql oracle-sqldeveloper


    【解决方案1】:

    首先,根本不需要使用 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 年 5 月 15 日,结束日期为 2013 年 5 月 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
                )
    

    现在,您要查找特定员工在给定日期之间的休假数。由于您的表已正确规范化,您只需 GROUP BY EMP_NUM 即可为每个员工获取它。

    假设您希望在 2013 年 5 月 15 日到 2013 年 5 月 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
                )
    

    【讨论】:

      【解决方案2】:

      如果我遇到这个问题,我会创建一个日历表,JOIN using BETWEEN paa.date_start AND paa.date_end;这样,无论他们的休假何时开始或结束,我都知道他们是否在任何一天都休假。如果从那里您有兴趣了解他们休了多少假,将连续天定义为休假的一个实例,那么您只需要找出休假天数之间的间隔即可。

      【讨论】:

      • 根本没有得到你的解决方案。我是一个初学者。请解释
      • 我从您的嵌套循环中假设您不是初学者,只是在寻找替代方法。如果您添加数据样本和预期输出样本,那么提供帮助会更容易。
      • 嘿,我习惯用 javascript 编码 :) 我试图通过表格来描述它。请检查
      • 这很有帮助,最终结果是您想知道某人在任何时间段内休假了多少天,或者他们在那段时间里休了多少不同的假期?即,我在一个月内离开了两周,但是这两周被我不休假的一周分开,你想知道我休了 2 次假期,或者我在这期间离开了 10 天那个时候?
      • 假设我从 2013 年 1 月 1 日到 2013 年 1 月 10 日休假时,请查看我编写的代码完美工作:- 1. 我通过了 2013 年 1 月 1 日的开始日期和 2013 年 1 月 1 日的结束日期-Jan-2013 2. 我将开始日期传递为 2013 年 1 月 1 日,结束日期为空 3. 我将开始日期传递为空,结束日期为 2013 年 1 月 10 日但假设我将开始日期传递为 1 月 2 日- 2013 年。现在虽然员工从 2013 年 1 月 2 日起没有请假,但他从 2013 年 1 月 1 日到 10 日请了假,所以这个假期也应该出现吧?但它没有出现。我希望现在我有点清楚了:)
      猜你喜欢
      • 1970-01-01
      • 2018-11-11
      • 1970-01-01
      • 1970-01-01
      • 2016-07-28
      • 2016-11-15
      • 2010-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多