在 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 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 |