2013-08-31 6 views
0

я одну таблицы, per_all_peopl_f, со следующими столбцами:PL/SQL (Как рассчитать первый и последний день любого квартала любого года)

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+) с повторным данных и различных эффективных дат начала.

Мне нужно рассчитать численность рабочей силы. То есть число сотрудников, которые выходят из компании ежеквартально.

Следующие столбцы должны быть выбраны:

  • Численность персонала в 2012 (первый квартал)
  • Численность персонала в 2013 (первый квартал)
  • разница между двумя численностью персонала
  • % разница

Это должно быть сделано ежеквартально. то есть какой бы ни был квартал, который я передаю, численность рабочей силы должна рассчитываться в соответствии с этим.

Запрос я написал

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 
crate or replace procedure proc_name(l_quarter number, 
         p_person_id number, 
         l_year number) 
    cursor cur_var 
    is 
     select function_name(l_start_date ,l_end_date) EMP_2012, 
       function_name(l_start_date1,l_end_date1) EMP_2013, 
       function_name(l_start_date ,l_end_date)-function_name(l_start_date1,l_end_date1) Diff 
     from dual; 


Begin 
if(l_year=2012) 

if l_quarter =1 
then 
l_start_date :='01-Jan-2013'; 
l_end_date :='31-APR-2013'; 

elsif l_quarter =2 
then 
l_start_date :='01-May-2013'; 
l_end_date :='31-Aug-2013'; 

else 
l_start_date :='01-Sep-2013'; 
l_end_date :='31-Dec-2013'; 

end if; 
end if; 
if(l_year=2013) 

then 

if l_quarter =1 
then 
l_start_date :='01-Jan-2013'; 
l_end_date :='31-APR-2013'; 

elsif l_quarter =2 
then 
l_start_date :='01-May-2013'; 
l_end_date :='31-Aug-2013'; 

else 
l_start_date :='01-Sep-2013'; 
l_end_date :='31-Dec-2013'; 

end if; 
end if; 

for cur_val in cur_var 
loop 
dbms_output.put_line(cur_var.emp_2012 || cur_var.emp_2013 ||cur_var.diff) 

end loop 



end xx_pack_name ; 

Этот пакет занимает слишком много времени.

Есть ли другой способ рассчитать последний и первый день квартала любого года ????

А также, когда я расчет

процент function_name (l_start_date, l_end_date ) -function_name (l_start_date1, l_end_date1)/100

выход не приходит в отборном заявлении

+0

Разницы между численностью в одну четверти, и что в следующем не то же самое, как количество людей, которые ушли. –

+0

Да ... вот почему разница havet o быть calculatd –

+0

Вы, кажется, определяете квартальную численность как «общее число уникальных людей, которые были заняты в любое время в течение квартала». Или что-то. Ваш код "effective_start_date> = l_end_date и effective_end_date <= l_start_date" ... правильно ли эта логика? Похоже, он никогда не вернет результат. –

ответ

1

Я нахожу этот вопрос очень запутанным.Если вопрос заключается в том, чтобы вычислить четверть произвольной DATE то есть уже много примеров, как:

Как рассчитать четверть произвольной даты

Некоторые даты проведения испытаний:

create table lots_of_dates as 
select trunc(sysdate - level * 7) as d 
from dual 
connect by level <= 52; 

Найти кварталы:

select d, 
     to_char(d, 'YYYY-Q') as QUARTER, 
     trunc(d, 'Q') as Q_FIRST_DAY, 
     add_months(trunc(d, 'Q'), 3) - 1 as Q_LAST_DAY 
from lots_of_dates 
order by 1; 

Результаты:

D     QUARTE Q_FIRST_DAY  Q_LAST_DAY 
------------------ ------ ------------------ ------------------ 
02-SEP-12   2012-3 01-JUL-12   30-SEP-12 
09-SEP-12   2012-3 01-JUL-12   30-SEP-12 
16-SEP-12   2012-3 01-JUL-12   30-SEP-12 
23-SEP-12   2012-3 01-JUL-12   30-SEP-12 
30-SEP-12   2012-3 01-JUL-12   30-SEP-12 
07-OCT-12   2012-4 01-OCT-12   31-DEC-12 
14-OCT-12   2012-4 01-OCT-12   31-DEC-12 
21-OCT-12   2012-4 01-OCT-12   31-DEC-12 
28-OCT-12   2012-4 01-OCT-12   31-DEC-12 
04-NOV-12   2012-4 01-OCT-12   31-DEC-12 
11-NOV-12   2012-4 01-OCT-12   31-DEC-12 
... 

это процедура PL/SQL, которая возвращает первые и последние дни четверти

начала и конец квартала в даты являются постоянными на протяжении всех лет, за исключением года. То есть второй квартал всегда начинается 1 апреля и заканчивается 30 июня каждый год. Таким образом, день и месяц могут быть исправлены, и только часть года должна быть скорректирована.

Функция может возвращать только одно значение, поэтому подпрограмма реализуется вместо процедуры. Я также предусмотрел функцию обертки к процедуре:

-- raises CASE_NOT_FOUND for non-existing quarters 
create or replace procedure get_quarter_days(
    p_year in number, 
    p_quarter in number, 
    p_first_day out date, 
    p_last_day out date 
) deterministic as 
begin 
    case p_quarter 
    when 1 then 
     p_first_day := to_date(p_year || '-01-01', 'YYYY-MM-DD'); 
     p_last_day := to_date(p_year || '-03-31', 'YYYY-MM-DD'); 
    when 2 then 
     p_first_day := to_date(p_year || '-04-01', 'YYYY-MM-DD'); 
     p_last_day := to_date(p_year || '-06-30', 'YYYY-MM-DD'); 
    when 3 then 
     p_first_day := to_date(p_year || '-07-01', 'YYYY-MM-DD'); 
     p_last_day := to_date(p_year || '-09-30', 'YYYY-MM-DD'); 
    when 4 then 
     p_first_day := to_date(p_year || '-10-01', 'YYYY-MM-DD'); 
     p_last_day := to_date(p_year || '-12-31', 'YYYY-MM-DD'); 
    end case; 
end; 
/
show errors 

create or replace function get_quarter_first_day(
    p_year in number, 
    p_quarter in number 
) return date deterministic as 
    v_first_day date; 
    v_last_day date; 
begin 
    get_quarter_days(p_year, p_quarter, v_first_day, v_last_day); 
    return v_first_day; 
end; 
/
show errors 

create or replace function get_quarter_last_day(
    p_year in number, 
    p_quarter in number 
) return date deterministic as 
    v_first_day date; 
    v_last_day date; 
begin 
    get_quarter_days(p_year, p_quarter, v_first_day, v_last_day); 
    return v_last_day; 
end; 
/
show errors 

Как использовать подпрограммы выше:

declare 
    v_first_day date; 
    v_last_day date; 
begin 
    get_quarter_days(2011, 1, v_first_day, v_last_day); 
    dbms_output.put_line(v_first_day || ' - ' || v_last_day); 
    get_quarter_days(2012, 2, v_first_day, v_last_day); 
    dbms_output.put_line(v_first_day || ' - ' || v_last_day); 
    get_quarter_days(2013, 3, v_first_day, v_last_day); 
    dbms_output.put_line(v_first_day || ' - ' || v_last_day); 
    get_quarter_days(2014, 4, v_first_day, v_last_day); 
    dbms_output.put_line(v_first_day || ' - ' || v_last_day); 

    dbms_output.put_line(get_quarter_first_day(2015, 1) || ' - ' || 
         get_quarter_last_day(2015, 1)); 
end; 
/
+0

Привет, я хочу создать функцию, в которой я буду проходить год как параметр и квартал, а также в первый и последний день этого квартала приехать. –

Смежные вопросы