Oracle sql 在计算中使用前几行数据

Oracle sql using previous rows data in calculations

我有一个包含 06 列的 table T1,我想使用 select 查询获取新的两列。 这是 T1,我想获得两个额外的列(STOCK、WAUC):

CREATE TABLE T1 (MOUVEMENT NUMBER(2), OPERATION VARCHAR2(5), ITEM VARCHAR2(5), INPUT_QTY NUMBER(6, 2), OUTPUT_QTY NUMBER(6, 2), INPUT_PRICE NUMBER(6, 2), STOCK NUMBER(6, 2), WAUC NUMBER(6, 2));
INSERT ALL
INTO T1 VALUES(1, 'I', 'A', 1500,  0,      5,      1500,       5)
INTO T1 VALUES(2, 'I', 'A', 700,   0,      6,      2200,       5.31)
INTO T1 VALUES(3, 'O', 'A', 0,     800,    0,      1400,       5.31)
INTO T1 VALUES(4, 'I', 'A', 1000,  0,      5,      2400,       5.18)
INTO T1 VALUES(5, 'O', 'A', 0,     500,    0,      1900,       5.18)
INTO T1 VALUES(6, 'I', 'A', 1000,  0,      7,      2900,       5.8 )
INTO T1 VALUES(7, 'I', 'A', 2000,  0,      7,      4900,       6.28)
INTO T1 VALUES(8, 'I', 'A', 5000,  0,      7,      5400,       6.34)
INTO T1 VALUES(9, 'O', 'A', 0,     1000,   0,      4400,       6.34)
INTO T1 VALUES(10, 'I','A', 1000,  0,      5,      5400,       6.09)
SELECT 1 FROM DUAL;

WAUC 就像是加权平均单位成本,可以使我们的库存稳定。

Ex for 2nd row : WAUC = ((5 * 1500) + (700 * 6)) / 2200 = 5.31

Ex for 3rd row : WAUC = last generated WAUC (5.31) of the same ITEM A.

我怎样才能做到这一点? 提前致谢。

您的逻辑是需要 model 子句的教科书示例,几乎可以按照您详细指定的方式重写为该子句(请注意 model 子句是一个野兽,要了解更多信息,请参阅here or here or here):

with t1 (mouvement, operation, item, input_qty, output_qty, input_price, stock_expected, wauc_expected) as (
 select 1, 'I', 'A', 1500,  0,      5,      1500,       5    from dual union all
 select 2, 'I', 'A', 700,   0,      6,      2200,       5.31 from dual union all
 select 3, 'O', 'A', 0,     800,    0,      1400,       5.31 from dual union all
 select 4, 'I', 'A', 1000,  0,      5,      2400,       5.18 from dual union all
 select 5, 'O', 'A', 0,     500,    0,      1900,       5.18 from dual union all
 select 6, 'I', 'A', 1000,  0,      7,      2900,       5.8  from dual union all
 select 7, 'I', 'A', 2000,  0,      7,      4900,       6.28 from dual union all
 select 8, 'I', 'A', 500,  0,      7,      5400,       6.34 from dual union all
 select 9, 'O', 'A', 0,     1000,   0,      4400,       6.34 from dual union all
 select 10, 'I','A', 1000,  0,      5,      5400,       6.09 from dual
)
select * from (
  select t1.*, 0 as stock_actual, 0 as wauc_actual from t1
)
model
  dimension by (row_number() over (order by mouvement) as rn)
  measures (mouvement, operation, item, input_qty, output_qty, input_price, stock_expected, wauc_expected, stock_actual, wauc_actual)
  rules (
    stock_actual[any] = coalesce(stock_actual[cv(rn) - 1], 0) + case operation[cv(rn)]
      when 'I' then input_qty[cv(rn)]
      when 'O' then -output_qty[cv(rn)]
    end,
    wauc_actual[any] = case
      when cv(rn) = 1
        then input_price[cv(rn)]
      when operation[cv(rn)] = 'I'
        then trunc((wauc_actual[cv(rn) - 1] * stock_actual[cv(rn) - 1] + input_qty[cv(rn)] * input_price[cv(rn)]) / stock_actual[cv(rn)], 2)
      when operation[cv(rn)] = 'O'
        then wauc_actual[cv(rn) - 1]
    end
  )
order by mouvement

(我将 operation=5000->500 中的拼写错误更改为 mouvement=8 并添加了截断为 2 位数字 - 这都是我从您的预期结果中猜到的。)

Db fiddle here.

请注意,简单的分析函数不足以计算 wauc,因为它们只能访问输入数据集列的先前值,而不能访问由函数本身计算的列的值。对于 stock 可以使用 运行 总计 sum(input_qty) over (order by mouvement) - sum(output_qty) over (order by mouvement) 但对于 wauc 几乎没有任何明确的公式。