Apr. 12th, 2014

egorius: (Default)

Вот еще задача из реальной жизни: округление копеек. Путь имеется отчет, показывающий какие-то денежные показатели; суммы надо выводить с точностью до копеек.

Для наглядности возьмем что-нибудь совсем тривиальное. Например, распределим общие затраты (расходы на электроэнергию) на все подразделения компании пропорционально их численности:

with depts(dept_id, quantity) as (
  select 1, 300 from dual union all
  select 2, 300 from dual union all
  select 3, 100 from dual union all
  select 4, 100 from dual union all
  select 5, 100 from dual
),
expenditures(amount) as (
  select 1000 from dual
),
report(dept_id,amount) as( 
  select   d.dept_id,
           e.amount * ratio_to_report(d.quantity) over ()
  from     depts d,
           expenditures e
)
select   dept_id,
         round(amount,2) amount
from     report;

DEPT_ID AMOUNT 
------- ------ 
      1 333,33 
      2 333,33 
      3 111,11 
      4 111,11 
      5 111,11

Какая досада, копеечка-то потерялась! Бухгалтер, работающий с РСБУ, этого не переживет.

Чтобы получилось правильно, надо учесть ошибки округления. Обычно их собирают вместе и добавляют к строке с максимальной суммой.

Чисто процедурных решений мне на практике не попадалось, но страшненький код видел и даже в детстве сам писал. Например, можно загнать еще не округленные результаты отчета в таблицу и поиздеваться над ней:

declare
  total     number;
  new_total number;
  max_dept  number;
begin
  select   round(sum(amount),2)
  into     total
  from     tmp;

  update   tmp
  set      amount = round(amount,2);
  
  select   sum(amount)
  into     new_total
  from     tmp;

  if total = new_total then
    return;
  end if;

  select   dept_id
  into     max_dept
  from     tmp
  where    amount = (
             select max(amount) from tmp
           )
       and rownum = 1;
       
  update   tmp
  set      amount = amount + total - new_total
  where    dept_id = max_dept;
end;
/

А одной командой SQL? )

Profile

egorius: (Default)
egorius

July 2025

M T W T F S S
  12 3 4 5 6
7891011 12 13
1415 1617181920
21222324252627
28293031   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Aug. 13th, 2025 03:47 pm
Powered by Dreamwidth Studios