1

我有一张表 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. % 区别

我用来按季度查找人数的查询是:

功能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  ;

这是否具有成本效益?

4

1 回答 1

0

如果至少有索引effective_start_date和表effective_end_date的字段,这似乎是一个很好的变体per_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 中使用结果(我想是因为返回单行)根本不使用游标,只需通过输出参数返回计算值。从另一个角度来看,如果您需要在一个游标中获取全年的季度数据,那么计算所有季度并在单个查询中进行比较可能会更有效。

于 2013-08-29T11:20:46.070 回答