Oracle SQL/PLSQL: 分层递归查询

Oracle SQL/PLSQL: Hierarchical recursive query

我以前问过非常相似的问题,但仍然没有得到正确的结果...第三次魅力,但我现在有稳定的 parent-child 工作关系。

multi-level 数据集中的每一行都有一个成本。对于特定行,我需要找到最低级别和 roll-up 成本。然后,我的用户会将汇总成本与行成本进行比较,然后进行故障排除 when/if 他们会发现差异。

SQL Fiddle here

数据样本:

MODEL_NO    MODEL_REV   P_SEQ_NO    SEQ_NO  UNIT_COST   QTY LEVEL   TREE_PATH   ISLEAF
1000    1   100 300 8889    1   1   >300    0
1000    1   300 400 1701    1   2   >300>400    1
1000    1   300 500 970 1   2   >300>500    1
1000    1   300 600 7   2   2   >300>600    1
1000    1   300 700 1160    1   2   >300>700    1
1000    1   300 800 580 1   2   >300>800    1
1000    1   300 900 96  1   2   >300>900    1
1000    1   300 1000    350 1   2   >300>1000   1
1000    1   300 1100    59  4   2   >300>1100   0
1000    1   1100    1200    28  1   3   >300>1100>1200  1
1000    1   1100    1300    1   1   3   >300>1100>1300  1
1000    1   1100    1400    3   1   3   >300>1100>1400  1
1000    1   1100    1500    4   1   3   >300>1100>1500  1
1000    1   1100    1600    22  1   3   >300>1100>1600  1

我正在寻找函数或 SQL 语句,基于数据集中的特定行(MODEL_NOMODEL_REVP_SEQ_NOSEQ_NO 制作一个唯一的密钥)将 return 成本 roll-up.

例如: 基于此记录:1000, 1, 300, 1100, 我期望的结果是:232.

这是通过将每个最低级别 child 的 UNIT_COST 乘以其 QTY,将每个 child 的总和相加,然后乘以结果得出的通过 parent 的 QTY,重复最后一步,直到您输入每条记录,在本例中为 SEQ_NO = 1100.

结果工作:(22*1 + 4*1 + 3*1 + 1*1 + 28*1) *4

这个例子只有 1 级深,我的数据可以达到 6/7 级。

我认为你需要分两步完成。

在第 1 步中,您创建分层查询结果并将数量分解到每个级别。例如,如果您有一条类似 100->210->320 的路径,并且这些路径的 qty 值分别为 2、3 和 5,那么您的分解数量分别为 2、6 和 30。

然后,有了它,您可以将这些展开的数量乘以单位代码,得到该行将占其所有 parent 级别的总成本的多少。然后,您可以使用标量子查询汇总这些成本。

这里是查询:

WITH c ( model_no, model_rev, lvl, p_seq_no, seq_no, unit_cost, qty, exploded_qty, pth) AS 
          ( SELECT model_no, model_rev, 1 lvl, p_seq_no, seq_no, unit_cost, qty, qty exploded_qty, to_char(seq_no) pth
            FROM   prod_cost_model_struct_tab
            WHERE  model_no = 1000
            AND    model_rev = 1
            AND    seq_no = 300
            UNION ALL 
            SELECT child.model_no, child.model_rev, parent.lvl+1, child.p_seq_no, child.seq_no, child.unit_cost, child.qty, parent.exploded_qty * child.qty exploded_qty, parent.pth || '>' || child.seq_no pth
            FROM   prod_cost_model_struct_tab child INNER JOIN c parent
            ON     child.model_no = parent.model_no
            AND    child.model_rev = parent.model_rev
            AND    child.p_seq_no = parent.seq_no )
            search depth first by seq_no set ord,
 exploded_qtys AS (            
        SELECT lvl, 
               c.p_seq_no,
               c.seq_no,
               c.unit_cost,
               c.qty,
               c.exploded_qty,
               c.pth,
               c.ord,
               case when (lvl - lead(lvl) over (order by ord)) < 0 then
                 -- It is not a leaf, level contributes nothing (assumption: see question)
                 -- QUESTION: What does the unit_cost represent on non-leaf rows?
                 0 ELSE c.exploded_qty * c.unit_cost END level_cost_contribution
        FROM c )
SELECT e.*, ( SELECT nvl(sum(level_cost_contribution),0) FROM exploded_qtys e2 WHERE e2.pth LIKE e.pth || '>%' ) + level_cost_contribution aggregate_cost
FROM exploded_qtys e
+-----+----------+--------+-----------+-----+--------------+---------------+-----+-------------------------+----------------+
| LVL | P_SEQ_NO | SEQ_NO | UNIT_COST | QTY | EXPLODED_QTY |      PTH      | ORD | LEVEL_COST_CONTRIBUTION | AGGREGATE_COST |
+-----+----------+--------+-----------+-----+--------------+---------------+-----+-------------------------+----------------+
|   1 |      100 |    300 |      8889 |   1 |            1 | 300           |   1 |                       0 |           8783 |
|   2 |      300 |    400 |      1701 |   1 |            1 | 300>400       |   2 |                    1701 |           1701 |
|   2 |      300 |    500 |       970 |   1 |            1 | 300>500       |   3 |                     970 |            970 |
|   2 |      300 |    600 |         7 |   2 |            2 | 300>600       |   4 |                      14 |             14 |
|   2 |      300 |    700 |      1160 |   1 |            1 | 300>700       |   5 |                    1160 |           1160 |
|   2 |      300 |    800 |       580 |   1 |            1 | 300>800       |   6 |                     580 |            580 |
|   2 |      300 |    900 |        96 |   1 |            1 | 300>900       |   7 |                      96 |             96 |
|   2 |      300 |   1000 |       350 |   1 |            1 | 300>1000      |   8 |                     350 |            350 |
|   2 |      300 |   1100 |        59 |   4 |            4 | 300>1100      |   9 |                       0 |            232 |
|   3 |     1100 |   1200 |        28 |   1 |            4 | 300>1100>1200 |  10 |                     112 |            112 |
|   3 |     1100 |   1300 |         1 |   1 |            4 | 300>1100>1300 |  11 |                       4 |              4 |
|   3 |     1100 |   1400 |         3 |   1 |            4 | 300>1100>1400 |  12 |                      12 |             12 |
|   3 |     1100 |   1500 |         4 |   1 |            4 | 300>1100>1500 |  13 |                      16 |             16 |
|   3 |     1100 |   1600 |        22 |   1 |            4 | 300>1100>1600 |  14 |                      88 |             88 |
|   2 |      300 |   1700 |       219 |   1 |            1 | 300>1700      |  15 |                       0 |            218 |
|   3 |     1700 |   1800 |        10 |   1 |            1 | 300>1700>1800 |  16 |                      10 |             10 |
|   3 |     1700 |   1900 |         1 |   4 |            4 | 300>1700>1900 |  17 |                       4 |              4 |
|   3 |     1700 |   2000 |       200 |   1 |            1 | 300>1700>2000 |  18 |                     200 |            200 |
|   3 |     1700 |   2100 |         4 |   1 |            1 | 300>1700>2100 |  19 |                       4 |              4 |
|   2 |      300 |   2200 |      1160 |   1 |            1 | 300>2200      |  20 |                    1160 |           1160 |
|   2 |      300 |   2300 |         1 |   8 |            8 | 300>2300      |  21 |                       8 |              8 |
|   2 |      300 |   2400 |         1 |   2 |            2 | 300>2400      |  22 |                       2 |              2 |
|   2 |      300 |   2500 |         1 |   1 |            1 | 300>2500      |  23 |                       1 |              1 |
|   2 |      300 |   2600 |         2 |   1 |            1 | 300>2600      |  24 |                       2 |              2 |
|   2 |      300 |   2700 |         4 |   2 |            2 | 300>2700      |  25 |                       8 |              8 |
|   2 |      300 |   2800 |       103 |   1 |            1 | 300>2800      |  26 |                     103 |            103 |
|   2 |      300 |   2900 |        95 |   1 |            1 | 300>2900      |  27 |                      95 |             95 |
|   2 |      300 |   3000 |         0 |   4 |            4 | 300>3000      |  28 |                       0 |              0 |
|   2 |      300 |   3100 |         2 |   1 |            1 | 300>3100      |  29 |                       2 |              2 |
|   2 |      300 |   3200 |         0 |  66 |           66 | 300>3200      |  30 |                       0 |              0 |
|   2 |      300 |   3300 |         0 |  12 |           12 | 300>3300      |  31 |                       0 |              0 |
|   2 |      300 |   3400 |         0 |  33 |           33 | 300>3400      |  32 |                       0 |              0 |
|   2 |      300 |   3500 |         0 |   4 |            4 | 300>3500      |  33 |                       0 |              0 |
|   2 |      300 |   3600 |         0 |   8 |            8 | 300>3600      |  34 |                       0 |              0 |
|   2 |      300 |   3700 |         0 |   4 |            4 | 300>3700      |  35 |                       0 |              0 |
|   2 |      300 |   3800 |         0 |   4 |            4 | 300>3800      |  36 |                       0 |              0 |
|   2 |      300 |   3900 |         0 |   5 |            5 | 300>3900      |  37 |                       0 |              0 |
|   2 |      300 |   4000 |         0 |  84 |           84 | 300>4000      |  38 |                       0 |              0 |
|   2 |      300 |   4100 |         0 |  32 |           32 | 300>4100      |  39 |                       0 |              0 |
|   2 |      300 |   4200 |         0 |  32 |           32 | 300>4200      |  40 |                       0 |              0 |
|   2 |      300 |   4300 |         1 |  12 |           12 | 300>4300      |  41 |                      12 |             12 |
|   2 |      300 |   4400 |         2 |   3 |            3 | 300>4400      |  42 |                       6 |              6 |
|   2 |      300 |   4500 |       145 |   1 |            1 | 300>4500      |  43 |                     145 |            145 |
|   2 |      300 |   4600 |        48 |   1 |            1 | 300>4600      |  44 |                      48 |             48 |
|   2 |      300 |   4700 |         2 |   2 |            2 | 300>4700      |  45 |                       4 |              4 |
|   2 |      300 |   4800 |      1846 |   1 |            1 | 300>4800      |  46 |                       0 |           1832 |
|   3 |     4800 |   4900 |       169 |   3 |            3 | 300>4800>4900 |  47 |                     507 |            507 |
|   3 |     4800 |   5000 |        30 |   1 |            1 | 300>4800>5000 |  48 |                      30 |             30 |
|   3 |     4800 |   5100 |        17 |   1 |            1 | 300>4800>5100 |  49 |                      17 |             17 |
|   3 |     4800 |   5200 |       169 |   3 |            3 | 300>4800>5200 |  50 |                     507 |            507 |
|   3 |     4800 |   5300 |         5 |   1 |            1 | 300>4800>5300 |  51 |                       5 |              5 |
|   3 |     4800 |   5400 |       320 |   1 |            1 | 300>4800>5400 |  52 |                     320 |            320 |
|   3 |     4800 |   5500 |        25 |   2 |            2 | 300>4800>5500 |  53 |                      50 |             50 |
|   3 |     4800 |   5600 |         5 |   4 |            4 | 300>4800>5600 |  54 |                      20 |             20 |
|   3 |     4800 |   5700 |        18 |   3 |            3 | 300>4800>5700 |  55 |                      54 |             54 |
|   3 |     4800 |   5800 |       139 |   2 |            2 | 300>4800>5800 |  56 |                     278 |            278 |
|   3 |     4800 |   5900 |         8 |   2 |            2 | 300>4800>5900 |  57 |                      16 |             16 |
|   3 |     4800 |   6000 |         9 |   1 |            1 | 300>4800>6000 |  58 |                       9 |              9 |
|   3 |     4800 |   6100 |        19 |   1 |            1 | 300>4800>6100 |  59 |                      19 |             19 |
|   2 |      300 |   6200 |        25 |   1 |            1 | 300>6200      |  60 |                      25 |             25 |
|   2 |      300 |   6300 |         9 |   1 |            1 | 300>6300      |  61 |                       9 |              9 |
+-----+----------+--------+-----------+-----+--------------+---------------+-----+-------------------------+----------------+

注意#1

您没有指出 unit_cost 代表层次结构中非叶节点的行。他们会以某种方式增加 children 的成本吗?这将改变答案。