参考上一行而不是父行的层次查询

问题描述 投票:1回答:1

我有一张表格,详细列出了具有当前状态的对象列表以及完成之前需要执行的操作的列表。

ProductId    CurrentWeight    RemainingRoute
001          50               M1-M7-M5
002          48               M3-M2-M9

我想如下将其转换为操作列表表

ProductId    CurrentWeight    Machine
001/1        50               M1
001/2        50               M7
001/3        50               M5
002/1        48               M3
002/2        48               M2
002/3        48               M9

使用此查询很容易:

SELECT ProductId || ‘/‘ || level, REGEXP_SUBSTR(RemainingRoute, ‘[^-]+’,1, LEVEL), CurrentWeight
FROM TABLE
CONNECT BY LEVEL <= REGEXP_COUNT(RemainingRoute, ‘-’) + 1
AND PRIOR ProductId = ProductId
AND PRIOR SYS_GUID() is not null;

这里是问题。我需要计算每次操作后产品掉落时的最终重量-每台机器的产量因数不同。

这意味着我需要一个层级查询,在这里我应该查看上一行(而不是父行)的权重,然后乘以相应机器的产量。

我当前的查询是:

SELECT REGEXP_SUBSTR(RemainingRoute, ‘[^-]+’,1, LEVEL), CASE LEVEL WHEN 1 THEN CurrentWeight ELSE ( CASE REGEXP_SUBSTR(RemainingRoute, ‘[^-]+’,1, LEVEL) WHEN ‘M1’ THEN 0.95 * PRIOR WeightAfter WHEN ‘M7’  THEN 0.9 * PRIOR WeightAfter END ) END AS WeightAfter
FROM TABLE
CONNECT BY LEVEL <= REGEXP_COUNT(RemainingRoute, ‘-’) + 1
AND PRIOR ProductId = ProductId
AND PRIOR SYS_GUID() is not null;

此查询确实有两个问题(不起作用)1.我想访问一个字段的上一个级别值,而不是父级别值-> PRIOR不是正确的命令2.我在权重变量定义中引用该字段时递归使用权重字段-我知道这是错误的,但不知道如何规避。

任何建议都值得赞赏

sql oracle recursive-query connect-by
1个回答
1
投票

您可能正在寻找下面显示的类似内容。注意,没有解析(和聚合)product函数,我不得不通过记录日志,解析sum和指数函数来模拟它。

我不明白为什么必须将productid和级别(我称其为“步骤”)组合在一个字符串中;当然,如果您愿意,也可以这样做,但是我以我认为应该的方式显示了输出。此外,在输出中,不清楚您必须显示什么重量(或更确切地说,为什么)-在产品到达机器之前或在机器处理之后的重量?我在每行上都显示了这两个值(以及开始处理之前的原始权重);确定您实际需要的报告。

我在WITH子句中模拟了您的输入,但是您当然应该使用实际的表(及其表名和列名)。我希望您在我的查询中有一个像MACHINES视图的表。我使用了左外部联接,以防万一机器实际上没有显示在MACHINES表中,尽管这是不允许的。 (但是,鉴于给定的数据模型直接违反第一范式,因此不确定如何执行[[enforce)。 。在此示例中,机器“ M9”会发生这种情况。

with sample_inputs (productid, currentweight, remainingroute) as ( select '001', 50, 'M1-M7-M5' from dual union all select '002', 48, 'M3-M2-M9' from dual ) , machines (machine, yield_factor) as ( select 'M1', 0.95 from dual union all select 'M7', 0.90 from dual union all select 'M3', 0.80 from dual union all select 'M4', 1.00 from dual union all select 'M6', 0.92 from dual union all select 'M2', 0.90 from dual union all select 'M5', 0.86 from dual ) , routes (productid, step, currentweight, machine) as ( select productid, level, currentweight, regexp_substr(remainingroute, '[^-]+', 1, level) from sample_inputs connect by level <= regexp_count(remainingroute, '[^-]+') and prior productid = productid and prior sys_guid() is not null ) , weights (productid, step, original_weight, machine, weight_out) as ( select r.productid, r.step, r.currentweight, r.machine, round(r.currentweight * exp(sum(ln(m.yield_factor)) over (partition by r.productid order by r.step)), 2) from routes r left outer join machines m on r.machine = m.machine ) select productid, step, original_weight, machine, lag(weight_out, 1, original_weight) over (partition by productid order by step) as weight_in, weight_out from weights order by productid, step;
输出:

PRODUCTID STEP ORIGINAL_WEIGHT MACHINE WEIGHT_IN WEIGHT_OUT ---------- ---- --------------- ------- --------------- --------------- 001 1 50.00 M1 50.00 47.50 001 2 50.00 M7 47.50 42.75 001 3 50.00 M5 42.75 36.76 002 1 48.00 M3 48.00 38.40 002 2 48.00 M2 38.40 34.56 002 3 48.00 M9 34.56 34.56

© www.soinside.com 2019 - 2024. All rights reserved.