Oracle SQL:如何使用递归函数进行产品过渡?

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

在 Oracle SQL 中,我有一个名为

kit_transition_mapping
的产品转换表,它是一个缓慢变化的维度和一个
orders
表。对于基于
order_no
order_date
,我需要利用
kit_transition_mapping
表来找到正确的套件。

例如,

  • 订单
    100
    放置在
    15-Aug-24
    上。由于在那一天
    ABC
    没有发生套件转换,我将使用原始套件
    ABC
  • 对于
    101
    ,由于订单日期介于 的过渡日期之间
    ABC
    我会将订单更新为新套件
    ABD
  • 对于
    102
    ,由于订单日期是
    15-Oct-24
    ,并且在该日期
    ABD
    过渡到
    ABE
    ,并且由于订单是针对
    ABC
    下的,我们将考虑之前从
    ABC
    的过渡ABD
    。因此,订单将是
    ABE
    而不是
    ABC

鉴于上述场景和将套件分解为

kit_component
级别的
component
表。如何编写查询以获得预期结果?

kit_transition_mapping

| old_kit | new_kit | valid_from | valid_to  |
|---------|---------|------------|-----------|
| ABC     | ABD     |  01-Sep-24 | 30-Sep-24 |
| ABD     | ABE     |  01-Oct-24 | 31-Oct-24 |
| ABE     | ABF     |  01-Nov-24 | 30-Nov-24 |

orders

| order_no | kit | order_date  | qty |
|----------|-----|-------------|-----|
| 100      | ABC |  15-Aug-24  | 1   |
| 101      | ABC |  15-Sep-24  | 1   |
| 102      | ABC |  15-Oct-24  | 1   |
| 103      | ABC |  15-Nov-24  | 1   |
| 104      | ABD |  15-Oct-24  | 1   |
| 105      | ABE |  15-Nov-24  | 1   |
| 106      | ABE |  15-Oct-24  | 1   |
| 107      | DEX |  01-Dec-24  | 1   |

kit_component

| kit | comp | qty |
|-----|------|-----|
| ABC | A    |   1 |
| ABC | B    |   2 |
| ABC | C    |   3 |
| ABD | A    |   1 |
| ABD | B    |   2 |
| ABD | D    |   4 |
| ABE | A    |   1 |
| ABE | B    |   2 |
| ABE | E    |   5 |
| ABF | A    |   1 |
| ABF | B    |   2 |
| ABF | F    |   6 |
| DEX | D    |   2 |
| DEX | E    |   3 |
| DEX | X    |   4 |

expected_result

| order_no | order_date | original_kit | new_kit | order_qty | comp | comp_qty |
|---------:|------------|--------------|---------|----------:|------|---------:|
|      100 | 15-Aug-24  | ABC          | ABC     |         1 | A    |        1 |
|      100 | 15-Aug-24  | ABC          | ABC     |         1 | B    |        2 |
|      100 | 15-Aug-24  | ABC          | ABC     |         1 | C    |        3 |
|      101 | 15-Sep-24  | ABC          | ABD     |         1 | A    |        1 |
|      101 | 15-Sep-24  | ABC          | ABD     |         1 | B    |        2 |
|      101 | 15-Sep-24  | ABC          | ABD     |         1 | D    |        4 |
|      102 | 15-Oct-24  | ABC          | ABE     |         1 | A    |        1 |
|      102 | 15-Oct-24  | ABC          | ABE     |         1 | B    |        2 |
|      102 | 15-Oct-24  | ABC          | ABE     |         1 | E    |        5 |
|      103 | 15-Nov-24  | ABC          | ABF     |         1 | A    |        1 |
|      103 | 15-Nov-24  | ABC          | ABF     |         1 | B    |        2 |
|      103 | 15-Nov-24  | ABC          | ABF     |         1 | F    |        6 |
|      104 | 15-Oct-24  | ABD          | ABE     |         1 | A    |        1 |
|      104 | 15-Oct-24  | ABD          | ABE     |         1 | B    |        2 |
|      104 | 15-Oct-24  | ABD          | ABE     |         1 | E    |        5 |
|      105 | 15-Nov-24  | ABE          | ABF     |         1 | A    |        1 |
|      105 | 15-Nov-24  | ABE          | ABF     |         1 | B    |        2 |
|      105 | 15-Nov-24  | ABE          | ABF     |         1 | F    |        6 |
|      106 | 15-Oct-24  | ABE          | ABE     |         1 | A    |        1 |
|      106 | 15-Oct-24  | ABE          | ABE     |         1 | B    |        2 |
|      106 | 15-Oct-24  | ABE          | ABE     |         1 | E    |        5 |
|      107 | 01-Dec-24  | DEX          | DEX     |         1 | D    |        2 |
|      107 | 01-Dec-24  | DEX          | DEX     |         1 | E    |        3 |
|      107 | 01-Dec-24  | DEX          | DEX     |         1 | X    |        4 |

以下是上述数据的 CTE:

WITH orders (order_no, kit, order_date, qty) AS (
    SELECT 100, 'ABC', DATE '2024-08-15', 1 FROM DUAL UNION ALL
    SELECT 101, 'ABC', DATE '2024-09-15', 1 FROM DUAL UNION ALL
    SELECT 102, 'ABC', DATE '2024-10-15', 1 FROM DUAL UNION ALL
    SELECT 103, 'ABC', DATE '2024-11-15', 1 FROM DUAL UNION ALL
    SELECT 104, 'ABD', DATE '2024-10-15', 1 FROM DUAL UNION ALL
    SELECT 105, 'ABE', DATE '2024-11-15', 1 FROM DUAL UNION ALL
    SELECT 106, 'ABE', DATE '2024-10-15', 1 FROM DUAL UNION ALL
    SELECT 107, 'DEX', DATE '2024-12-01', 1 FROM DUAL
),
kit_transition_mapping (old_kit, new_kit, valid_from, valid_to) AS (
    SELECT 'ABC', 'ABD', DATE '2024-09-01', DATE '2024-09-30' FROM DUAL UNION ALL
    SELECT 'ABD', 'ABE', DATE '2024-10-01', DATE '2024-10-31' FROM DUAL UNION ALL
    SELECT 'ABE', 'ABF', DATE '2024-11-01', DATE '2024-11-30' FROM DUAL
),
kit_component (kit, comp, qty) AS (
    SELECT 'ABC', 'A', 1 FROM DUAL UNION ALL
    SELECT 'ABC', 'B', 2 FROM DUAL UNION ALL
    SELECT 'ABC', 'C', 3 FROM DUAL UNION ALL
    SELECT 'ABD', 'A', 1 FROM DUAL UNION ALL
    SELECT 'ABD', 'B', 2 FROM DUAL UNION ALL
    SELECT 'ABD', 'D', 4 FROM DUAL UNION ALL
    SELECT 'ABE', 'A', 1 FROM DUAL UNION ALL
    SELECT 'ABE', 'B', 2 FROM DUAL UNION ALL
    SELECT 'ABE', 'E', 5 FROM DUAL UNION ALL
    SELECT 'ABF', 'A', 1 FROM DUAL UNION ALL
    SELECT 'ABF', 'B', 2 FROM DUAL UNION ALL
    SELECT 'ABF', 'F', 6 FROM DUAL UNION ALL
    SELECT 'DEX', 'D', 2 FROM DUAL UNION ALL
    SELECT 'DEX', 'E', 3 FROM DUAL UNION ALL
    SELECT 'DEX', 'X', 4 FROM DUAL
),
kit_resolution (order_no, original_kit, kit, order_date, order_qty) AS (
    SELECT ho.order_no, ho.kit AS original_kit, ho.kit, ho.order_date, ho.qty AS order_qty
    FROM orders ho
    UNION ALL
    SELECT kr.order_no, kr.original_kit, km.new_kit, kr.order_date, kr.order_qty
    FROM kit_resolution kr
    JOIN kit_transition_mapping km ON kr.kit = km.old_kit AND kr.order_date BETWEEN km.valid_from AND km.valid_to
)
SELECT 
    kr.order_no, 
    TO_CHAR(kr.order_date, 'DD-Mon-YY') AS order_date,
    kr.original_kit, 
    kr.kit AS new_kit, 
    kr.order_qty, 
    kc.comp, 
    kc.qty * kr.order_qty AS comp_qty
FROM kit_resolution kr
JOIN kit_component kc ON kr.kit = kc.kit
WHERE NOT EXISTS (
    SELECT 1 FROM kit_transition_mapping km
    WHERE kr.kit = km.old_kit AND kr.order_date BETWEEN km.valid_from AND km.valid_to
)
ORDER BY kr.order_no, kc.comp;
oracle-database hierarchical-data
1个回答
0
投票

从 Oracle 12 开始,您可以使用

LATERAL
连接进行分层查询,并使用
CONNECT_BY_ISLEAF
查找最深的祖先:

SELECT ho.order_no,
       ho.order_date,
       ho.kit AS original_kit,
       kc.kit AS new_kit,
       ho.qty AS order_qty,
       kc.comp,
       kc.qty AS comp_qty
FROM   orders ho
       LEFT OUTER JOIN LATERAL(
         SELECT km.new_kit
         FROM   kit_transition_mapping km
         WHERE  CONNECT_BY_ISLEAF = 1
         START WITH ho.kit = km.old_kit
         AND        ho.order_date BETWEEN km.valid_from AND km.valid_to
         CONNECT BY PRIOR km.new_kit = km.old_kit
         AND        ho.order_date BETWEEN km.valid_from AND km.valid_to
       ) km
       ON 1 = 1
       INNER JOIN kit_component kc
       ON kc.kit = COALESCE(km.new_kit, ho.kit)
ORDER BY ho.order_no, kc.comp

对于样本数据,输出:

订单号 订单_日期 原始套件 NEW_KIT 订单数量 比较 COMP_数量
100 2024-08-15 00:00:00 ABC ABC 1 A 1
100 2024-08-15 00:00:00 ABC ABC 1 B 2
100 2024-08-15 00:00:00 ABC ABC 1 C 3
101 2024-09-15 00:00:00 ABC ABD 1 A 1
101 2024-09-15 00:00:00 ABC ABD 1 B 2
101 2024-09-15 00:00:00 ABC ABD 1 D 4
102 2024-10-15 00:00:00 ABC ABC 1 A 1
102 2024-10-15 00:00:00 ABC ABC 1 B 2
102 2024-10-15 00:00:00 ABC ABC 1 C 3
103 2024-11-15 00:00:00 ABC ABC 1 A 1
103 2024-11-15 00:00:00 ABC ABC 1 B 2
103 2024-11-15 00:00:00 ABC ABC 1 C 3
104 2024-10-15 00:00:00 ABD 阿贝 1 A 1
104 2024-10-15 00:00:00 ABD 阿贝 1 B 2
104 2024-10-15 00:00:00 ABD 阿贝 1 E 5
105 2024-11-15 00:00:00 阿贝 ABF 1 A 1
105 2024-11-15 00:00:00 阿贝 ABF 1 B 2
105 2024-11-15 00:00:00 阿贝 ABF 1 F 6
106 2024-10-15 00:00:00 阿贝 阿贝 1 A 1
106 2024-10-15 00:00:00 阿贝 阿贝 1 B 2
106 2024-10-15 00:00:00 阿贝 阿贝 1 E 5
107 2024-12-01 00:00:00 DEX DEX 1 D 2
107 2024-12-01 00:00:00 DEX DEX 1 E 3
107 2024-12-01 00:00:00 DEX DEX 1 X 4

小提琴

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