每季度计算劳动力人数的效率

时间:2013-08-28 17:05:15

标签: sql oracle plsql

我有一个表per_all_peopl_f,其中包含以下列:

name  person_id  emp_flag  effective_start_date   effective_end_date   DOJ
--------------------------------------------------------------------------------    
ABC   123          Y       30-MAR-2011              30-MAR-2013       10-FEB-2011
ABC   123          Y       24-FEB-2011              27-FEB-2011       10-FEB-2011
DEF   345          N       10-APR-2012              30-DEC-4712       15-SEP-2011

有许多条目(1000+)包含重复数据和不同的有效开始日期。

我必须计算劳动力人数。也就是说,每季度退出公司的员工人数。

必须提取以下列:

  1. 2012年(第一季度)人数
  2. 2013年(第一季度)人数
  3. 两个人数之间的差异
  4. %差异
  5. 我过去常常查找人数的查询是:

    功能1:

    CREATE OR REPLACE FUNCTION function_name
      (l_end_date ,l_start_date  ) 
      RETURN number;
      IS 
        l_emp
    
      BEGIN
        select count(distinct papf.person_id)
          into l_emp
          from per_all_people_f papf
         where papf.emp_flag ='Y'
           and effective_start_date >=l_end_date
           and effective_end_date <=l_start_date ;
    
        return l_emp; 
    END function_name;
    

    主要包裹:

    create xx_pack_name  body
    is 
        cursor cur_var
        is 
           select function_name('01-MAR-2012','31-MAY-2012') EMP_2012,
                  function_name('01-MAR-2013','31-MAY-2013') EMP_2013,
                  function_name('01-MAR-2012','31-MAY-2012')-function_name('01-MAR-2013','31-MAY-2013') Diff
             from dual;
    
    end xx_pack_name  ;
    

    这是否具有成本效益?

1 个答案:

答案 0 :(得分:0)

如果effective_start_date表的至少effective_end_dateper_all_people_f字段都有索引,则似乎是一个很好的变体。

此查询的理想变体是

create index x_per_all_people_search on per_all_people_f(   
  effective_start_date,
  effective_end_date, 
  person_id,  
  emp_flag
)

但维护成本太高(磁盘成本,插入速度)。

此外,包体中的游标必须包含子查询并重用函数调用结果:

cursor cur_var
is 
  select 
    EMP_2012,
    EMP_2013,
    (EMP_2013 - EMP_2012) Diff
  from (
   select 
     function_name('01-MAR-2012','31-MAY-2012') EMP_2012,
     function_name('01-MAR-2013','31-MAY-2013') EMP_2013
   from dual
  );

当然,最好的解决方案是最小化上下文切换并从单个SQL查询中获取所有值。此外,您可以直接向光标提供参数:

cursor cur_var(
  start_1 date, end_1 date, 
  start_2 date, end_2 date
)
is 
  select 
    EMP_2012,
    EMP_2013,
    (EMP_2013 - EMP_2012) Diff
  from (
   select 
     (
       select 
         count(distinct papf.person_id)
       from 
         per_all_people_f papf
       where 
         papf.emp_flag = 'Y'
         and 
         effective_start_date >= trunc(start_1)
         and 
         effective_end_date   <= trunc(end_1)
     ) EMP_2012,
     (
       select 
         count(distinct papf.person_id)
       from 
         per_all_people_f papf
       where 
         papf.emp_flag = 'Y'
         and 
         effective_start_date >= trunc(start_2)
         and 
         effective_end_date   <= trunc(end_2)
     ) EMP_2013
   from dual
  );

从我的观点来看,函数/游标参数过于通用,可能更好的创建一个包装器,它将输入参数作为季度数和两年进行比较。

最后,如果计划在PL / SQL中使用的结果(我想由于返回单行)不使用游标,只需通过输出参数返回计算值。从另一个角度来看,如果你需要在一个光标中获得全年的季度数据,那么计算所有季度并在单个查询中进行比较可能更有效。