2015-10-01 4 views
0

Я хотел бы сделать расчет prorata в PL/SQL, но я не знаю, как это сделать.Как вычислить вычисление prorata в PL/SQL?

Вот мой Exemple:

ID class Wages Premium 
1  A 15000  250 
2  A 10000  0 

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

Здесь для ID 1, она: гавань

premium = (10000 * 250)/(25000) = 100 

Очевидно, что я должен сделать это на более объемные данных ... Но я:

premium = (15000 *sum(premium))/(sum(wages)) = (15000 * 250)/(25000) = 150 

Таким образом, для ID 2 «т сделано много PL/SQL до сих пор ...

Я могу добавить, что я должен сделать это throgh инструкции обновления ...

Не могли бы вы мне помочь?

Большое спасибо

+0

Почему вы хотите хранимую процедуру? –

ответ

2

Наиболее эффективным методом было бы использовать ratio_to_report(), которое часто странно игнорируется.

select id, 
     premium, 
     sum(premium) over (partition by class) * 
     ratio_to_report(wages) over (partition by class) prorated_premium 
from my_table 

Для обновления я хотел бы посмотреть на:

update (query from above) 
set premium = prorated_premium 
0

Попробуйте;

with data(class, sum_pre, sum_wage) as (
    select class, sum(Premium), sum(Wages) 
    from tbl 
    group by class 
) 
select t.ID, t.class 
    t.Wages * s.sum_pre/ s.sum_wage as val 
from tbl t 
join data s on s.class = t.class 

Для обновления

MERGE 
INTO tbl t 
USING (
    with data(class, sum_pre, sum_wage) as (
     select class, sum(Premium), sum(Wages) 
     from tbl 
     group by class 
    ) 
    select t.ID 
     t.Wages * s.sum_pre/ s.sum_wage as val 
    from tbl t 
    join data s on s.class = t.class 
) x 
ON (x.ID = t.ID) 
WHEN MATCHED THEN 
UPDATE 
SET premium = x.val; 
1

Вы можете легко вычислить новые значения премиум с аналитическими функциями:

create table prorata_test as 
select 1 id, 
     'A' class, 
     15000 wages, 
     250 premium 
from dual 
union all 
select 2 id, 
     'A' class, 
     10000 wages, 
     0 premium 
from dual 
union all 
select 3 id, 
     'B' class, 
     10000 wages, 
     50 premium 
from dual; 

select id, 
     class, 
     wages, 
     premium, 
     sum(wages) over (partition by class) tot_wages, 
     sum(premium) over (partition by class) tot_premium, 
     wages * sum(premium) over (partition by class)/sum(wages) over (partition by class) new_premium 
from prorata_test; 

     ID CLASS  WAGES PREMIUM TOT_WAGES TOT_PREMIUM NEW_PREMIUM 
---------- ----- ---------- ---------- ---------- ----------- ----------- 
     1 A   15000  250  25000   250   150 
     2 A   10000   0  25000   250   100 
     3 B   10000   50  10000   50   50 

Таким образом, вы можете видеть, что аналитические функции суммы, которые рассчитывают tot_wages и to_premium столбцы суммируют значения по каждому классу (это то, что мы разделили на (aka grouped by)), и поэтому вы можете просто использовать их в вычислении new_premium.

Чтобы сохранить новое значение премиум, вы должны использовать MERGE заявление с выше запроса в наборе исходных данных, например, так:

merge into prorata_test tgt 
using (select id, 
       class, 
       wages, 
       premium, 
       wages * sum(premium) over (partition by class)/sum(wages) over (partition by class) new_premium 
     from prorata_test) src 
    on (tgt.id = src.id) 
when matched then 
update set tgt.premium = src.new_premium; 

commit; 

select * 
from prorata_test 
order by id; 

     ID CLASS  WAGES PREMIUM 
---------- ----- ---------- ---------- 
     1 A   15000  150 
     2 A   10000  100 
     3 B   10000   50 

нотабене Я предполагаю, что идентификатор является первичным ключом (или, по крайней мере, уникальным по всей таблице!).

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