繁体   English   中英

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

[英]Oracle sql using previous rows data in calculations

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

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 就像加权平均单位成本来评估我们的库存。

  • 如果第一个记录:STOCK = INPUT 和 WAUC = INPUT_PRICE;
  • 如果新 INPUT 操作:新 WAUC 应该是:(最后生成的 WAUC * 最后生成的库存)+(当前 INPUT * 当前 INPUT_PRICE))/当前生成的 STOCK。

例如第二行:WAUC = ((5 * 1500) + (700 * 6)) / 2200 = 5.31

  • 如果新的 OUTPUT 操作:WAUC 应该是最后生成的 WAUC。

例如,第 3 行:WAUC = 同一项目 A 的最后生成的 WAUC (5.31)。

  • 意味着,每个新的 INPUT 操作都应该更改 WAUC。
  • 在我看来,STOCK 和 WAUC 应该即时生成,而不是作为记录,因为否则,只有一个意外错误的 INPUT_PRICE,会导致错误的下一个 WAUC(s)-> 错误的下一个计算(s)->(错误的工作)。

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

您的逻辑是需要model子句的教科书示例,并且几乎可以按照您详细指定的方式重写为该子句(注意model子句是野兽,要了解有关它的更多信息,请参见此处此处此处):

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小提琴在这里。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM