【问题标题】:Use oracle LAG function data in calculations在计算中使用 oracle LAG 函数数据
【发布时间】:2022-01-18 05:46:01
【问题描述】:

我想获得库存和加权平均单位成本WAUC

表 T1:

ROW ITEM IN OUT PRICE STOCK WAUC
1 A 1000 - 20 1000 20
2 A 2000 - 25 - -
3 A 1500 - 15 - -
4 A 500 - 20 - -

我有前 5 列和后两列的前两条记录,并想获取后两列的其余部分 STOCKWAUC

WAUC = ((PREVIOUS_PRICE * PREVIOUS_STOCK) + (CURRENT_IN * CURRENT_PRICE)) / CURRENT_STOCK

所以,我写了查询:

SELECT ROW,
       SUM(IN - OUT) OVER(ORDER BY ROW) STOCK,
       ((LAG(STOCK * WAUC) OVER (ORDER BY ROW)) + (IN * PRICE)) / STOCK AS WAUC
FROM T1

我想要的是:

ROW ITEM IN OUT PRICE STOCK WAUC
1 A 1000 - 20 1000 20
2 A 2000 - 25 3000 23.33
3 A 1500 - 15 4500 20.55
4 A 500 - 20 5000 20.49

也就是说,我想在计算数据中使用LAG结果。

【问题讨论】:

  • 您似乎认为“滞后”意味着“运行”(从第一行到当前行)。这不是“滞后”的意思。
  • 注意:ROW 是保留字。 INOUT 也是如此。避开他们。

标签: sql oracle sql-update lag


【解决方案1】:

你的公式应该是:

WAUC = (
         PREVIOUS_WAUC * PREVIOUS_STOCK
       + (CURRENT_IN - CURRENT_OUT) * CURRENT_PRICE
       )
       / CURRENT_STOCK

您可以使用MODEL 子句(通过一些额外的测量来简化计算):

SELECT "ROW", item, "IN", "OUT", price, stock, wauc
FROM   t1
MODEL
  DIMENSION BY ("ROW")
  MEASURES (item, "IN", "OUT", price, 0 AS change, 0 AS stock, 0 AS total, 0 AS wauc)
  RULES (
    change["ROW"] = COALESCE("IN"[cv()], 0) - COALESCE("OUT"[cv()], 0),
    stock["ROW"]  = change[cv()] + COALESCE(stock[cv()-1], 0),
    total["ROW"]  = change[cv()] * price[cv()] + COALESCE(total[cv()-1], 0),
    wauc["ROW"]   = total[cv()] / stock[cv()]
);

或者,在 Oracle 12 中,使用 MATCH_RECOGNIZE

SELECT "ROW",
       item,
       "IN",
       "OUT",
       price,
       total_stock AS stock,
       total_cost / total_stock AS wauc
FROM   t1
MATCH_RECOGNIZE(
  ORDER BY "ROW"
  MEASURES
    SUM(COALESCE("IN", 0) - COALESCE("OUT", 0)) AS total_stock,
    SUM((COALESCE("IN", 0) - COALESCE("OUT", 0))*price) AS total_cost
  ALL ROWS PER MATCH
  PATTERN (all_rows+)
  DEFINE
    all_rows AS 1 = 1
)

或解析函数:

SELECT "ROW",
       item,
       "IN",
       "OUT",
       price,
       SUM(COALESCE("IN",0) - COALESCE("OUT", 0)) OVER (ORDER BY "ROW")
         AS stock,
       SUM((COALESCE("IN",0) - COALESCE("OUT", 0))*price) OVER (ORDER BY "ROW")
        / SUM(COALESCE("IN",0) - COALESCE("OUT", 0)) OVER (ORDER BY "ROW")
        AS wauc
FROM   t1

其中,对于样本数据:

CREATE TABLE t1 ("ROW", ITEM, "IN", "OUT", PRICE, STOCK, WAUC) AS
SELECT 1, 'A', 1000, CAST(NULL AS NUMBER), 20, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER) FROM DUAL UNION ALL
SELECT 2, 'A', 2000, NULL, 25, NULL, NULL FROM DUAL UNION ALL
SELECT 3, 'A', 1500, NULL, 15, NULL, NULL FROM DUAL UNION ALL
SELECT 4, 'A',  500, NULL, 20, NULL, NULL FROM DUAL;

所有输出:

ROW ITEM IN OUT PRICE STOCK WAUC
1 A 1000 20 1000 20
2 A 2000 25 3000 23.33333333333333333333333333333333333333
3 A 1500 15 4500 20.55555555555555555555555555555555555556
4 A 500 20 5000 20.5

注意:ROWINOUT 是关键字,您不应将它们用作标识符,因为您必须在它们出现的任何地方使用带引号的标识符。

db小提琴here

【讨论】:

  • 大声笑 - 更改“分析函数”解决方案(从您提供的原始解决方案)是可以的,但是......到您进行更改时已经发布的解决方案?我期待更好。
【解决方案2】:

您的问题与“滞后”无关。

使用MT0的样本数据:

select "ROW", item, "IN", "OUT", price,
       sum(nvl("IN", 0) - nvl("OUT", 0)) 
           over (partition by item order by "ROW") as stock,
       round(sum((nvl("IN", 0) - nvl("OUT", 0)) * price)
           over (partition by item order by "ROW") 
       / sum(nvl("IN", 0) - nvl("OUT", 0))
           over (partition by item order by "ROW"), 2 ) as wauc
from   t1
;

   ROW ITEM     IN    OUT  PRICE  STOCK   WAUC
------ ---- ------ ------ ------ ------ ------
     1 A      1000            20   1000     20
     2 A      2000            25   3000  23.33
     3 A      1500            15   4500  20.56
     4 A       500            20   5000   20.5

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多