Я хочу вычислить затраты на инвентаризацию с использованием среднего значения, и я немного застрял здесь...
Рассмотрим простую таблицу транзакций tr
: (идентификаторы являются автоинкрементами, отрицательный том указывает на транзакцию продажи)
order_id | volume | price | type
1 | 1000 | 100 | B
2 | -500 | 110 | S
3 | 1500 | 80 | B
4 | -100 | 150 | S
5 | -600 | 110 | S
6 | 700 | 105 | B
Теперь я хочу узнать общий объем и общие затраты после каждой транзакции. Трудность заключается в получении прав на продажу. Продажи всегда оцениваются по средней стоимости на данный момент (т.е. цена продажи на самом деле здесь не актуальна), поэтому порядок транзакций имеет значение здесь.
Оптимально, результат будет выглядеть так:
order_id | volume | price | total_vol | total_costs | unit_costs
1 | 1000 | 100 | 1000 | 100000 | 100
2 | -500 | 110 | 500 | 50000 | 100
3 | 1500 | 80 | 2000 | 170000 | 85
4 | -100 | 150 | 1900 | 161500 | 85
5 | -600 | 110 | 1300 | 110500 | 85
6 | 700 | 105 | 2000 | 184000 | 92
Теперь total_vol легко с sum(volume) over (...)
, совокупными затратами, с другой стороны. Я играл с функциями окна, но, если мне не хватает чего-то совершенно очевидного (или очень умного), я не думаю, что это можно сделать только с помощью оконных функций...
Любая помощь будет оценена по достоинству.:)
UPDATE:
Это код, который я наконец использовал, комбинация обоих ответов (модель данных немного сложнее, чем мой упрощенный пример выше, но вы получаете идею):
select ser_num
, tr_id
, tr_date
, action_typ
, volume
, price
, total_vol
, trunc(total_costs,0) total_costs
, trunc(unit_costs,4) unit_costs
from itt
model
partition by (ser_num)
dimension by (row_number() over (partition by ser_num order by tr_date, tr_id) rn)
measures (tr_id, tr_date, volume, price, action_typ, 0 total_vol, 0 total_costs, 0 unit_costs)
rules automatic order
( total_vol[ANY] order by rn
= nvl(total_vol[cv()-1],0) +
decode(action_typ[cv()], 'Buy', 1, 'Sell', -1) * volume[cv()]
, total_costs[ANY] order by rn
= case action_typ[cv()]
when 'Buy' then volume[cv()] * price[cv()] + nvl(total_costs[cv()-1],0)
when 'Sell' then total_vol[cv()] * nvl(unit_costs[cv()-1],price[cv()])
end
, unit_costs[ANY] order by rn
= decode(total_vol[cv()], 0, unit_costs[cv()-1],
total_costs[cv()] / total_vol[cv()])
)
order by ser_num, tr_date, tr_id
Некоторые наблюдения:
- При использовании разделов и ссылок на предыдущую ячейку (
cv()-1
) измерение должно быть разделено так же, как и все предложение модели (это также связано с тем, что использование iteration_number может быть сложным) - Здесь не требуется итерации, если вы указываете правильный порядок выполнения правил (
order by rn
Automatic order
делает это автоматически) -
Автоматический порядок, вероятно, здесь не нужен, но он не может повредить.