我希望创建一个递归查询,能够将一系列补货完全映射到顶级需求。
以下是有关我的问题陈述的一些详细信息:
I am attempting to design a recursive solution to calculate all subsequent replenishments (and their levels) give a top level requirement, where a requirement is defined as a production or planned order (a
MIN
type)
我创建了这个SQLFIDDLE使用以下查询:
-- schema
CREATE TABLE tblInputs (
Type VARCHAR(256),
Order_No VARCHAR(256),
Planned_No VARCHAR(256),
Purchase_No VARCHAR(256),
Direction VARCHAR(256)
);
CREATE TABLE Requirements (
Order_No VARCHAR(256),
Planned_No VARCHAR(256),
Req_ID VARCHAR(256),
Req_No VARCHAR(256)
);
CREATE TABLE ReqRep (
Req_ID VARCHAR(256),
Req_No VARCHAR(256),
Rep_ID VARCHAR(256)
);
CREATE TABLE Replenishments (
Rep_ID VARCHAR(256),
Order_No VARCHAR(256),
Planned_No VARCHAR(256),
Purchase_No VARCHAR(256)
);
-- data
INSERT INTO tblInputs (Type, Order_No, Planned_No, Purchase_No, Direction)
SELECT 'Purchase', NULL, NULL, 'PO9000124798', 'PLUS' FROM DUAL
UNION ALL
SELECT 'Planned', NULL, 'PL191908851', NULL, 'PLUS' FROM DUAL
UNION ALL
SELECT 'Planned', NULL, 'PL191908852', NULL, 'PLUS' FROM DUAL
UNION ALL
SELECT 'Planned', NULL, 'PL191908853', NULL, 'PLUS' FROM DUAL
UNION ALL
SELECT 'Planned', NULL, 'PL191908854', NULL, 'PLUS' FROM DUAL
UNION ALL
SELECT 'Planned', NULL, 'PL191908855', NULL, 'PLUS' FROM DUAL
UNION ALL
SELECT 'Planned', NULL, 'PL191908853', NULL, 'PLUS' FROM DUAL
UNION ALL
SELECT 'Build', 'O103916639', NULL, NULL, 'MIN' FROM DUAL
UNION ALL
SELECT 'Production', 'O103962037', NULL, NULL, 'PLUS' FROM DUAL
UNION ALL
SELECT 'Production', 'O103933200', NULL, NULL, 'PLUS' FROM DUAL
;
INSERT INTO Requirements (Order_No, Planned_No, Req_ID, Req_No)
SELECT NULL, 'PL191908851', 'ABA', '36' FROM DUAL UNION ALL
SELECT NULL, 'PL191908852', 'CC', '93' FROM DUAL UNION ALL
SELECT NULL, 'PL191908853', 'BBA', '27' FROM DUAL UNION ALL
SELECT NULL, 'PL191908854', 'EWE', '42' FROM DUAL UNION ALL
SELECT NULL, 'PL191908855', 'WWW', '13' FROM DUAL UNION ALL
SELECT NULL, 'PL191908856', 'EEE', '33' FROM DUAL UNION ALL
SELECT NULL, 'PL191909922', 'GFW', '99' FROM DUAL UNION ALL
SELECT NULL, 'PL191910022', 'GFT', '23' FROM DUAL UNION ALL
SELECT NULL, 'PL192010120', 'THE', '54' FROM DUAL UNION ALL
SELECT 'O103962037', NULL, 'BDD', '37' FROM DUAL UNION ALL
SELECT 'O103933200', NULL, 'DFA', '63' FROM DUAL UNION ALL
SELECT 'O103547812', NULL, 'ADS', '45' FROM DUAL UNION ALL
SELECT 'O103547415', NULL, 'DWQ', '94' FROM DUAL UNION ALL
SELECT 'O103654787', NULL, 'QZX', '96' FROM DUAL UNION ALL
SELECT 'O103214217', NULL, 'NFD', '20' FROM DUAL UNION ALL
SELECT 'O103215320', NULL, 'GBV', '33' FROM DUAL UNION ALL
SELECT 'O106212219', NULL, 'ERQ', '22' FROM DUAL UNION ALL
SELECT 'O103215320', NULL, 'MRP', '11' FROM DUAL
;
INSERT INTO ReqRep (Req_ID, Req_No, Rep_ID)
SELECT 'ABA', '36', '7736' FROM DUAL UNION ALL
SELECT 'CCC', '93', '6686' FROM DUAL UNION ALL
SELECT 'BBA', '27', '5710' FROM DUAL UNION ALL
SELECT 'EWE', '42', '7634' FROM DUAL UNION ALL
SELECT 'WWW', '13', '9393' FROM DUAL UNION ALL
SELECT 'EEE', '33', '8442' FROM DUAL UNION ALL
SELECT 'GFW', '99', '5758' FROM DUAL UNION ALL
SELECT 'GFT', '23', '5988' FROM DUAL UNION ALL
SELECT 'THE', '54', '6748' FROM DUAL UNION ALL
SELECT 'BDD', '37', '7123' FROM DUAL UNION ALL
SELECT 'BDD', '37', '7124' FROM DUAL UNION ALL
SELECT 'BDD', '37', '7125' FROM DUAL UNION ALL
SELECT 'BDD', '37', '7126' FROM DUAL UNION ALL
SELECT 'DFA', '63', '7125' FROM DUAL UNION ALL
SELECT 'ADS', '45', '5855' FROM DUAL UNION ALL
SELECT 'DWQ', '80', '9419' FROM DUAL UNION ALL
SELECT 'QZX', '96', '5748' FROM DUAL UNION ALL
SELECT 'NFD', '20', '7055' FROM DUAL UNION ALL
SELECT 'ERQ', '22', '7736' FROM DUAL UNION ALL
SELECT 'MRP', '11', '7736' FROM DUAL UNION ALL
SELECT 'GBV', '33', '9999' FROM DUAL
;
INSERT INTO Replenishments(Rep_ID, Order_No, Planned_No, Purchase_No)
SELECT '7736', NULL, NULL, 'PO9000124799' FROM DUAL UNION ALL
SELECT '6686', NULL, NULL, 'PO9000124800' FROM DUAL UNION ALL
SELECT '5710', NULL, NULL, 'PO9000124801' FROM DUAL UNION ALL
SELECT '7634', NULL, NULL, 'PO9000124802' FROM DUAL UNION ALL
SELECT '9393', NULL, NULL, 'PO9000124803' FROM DUAL UNION ALL
SELECT '8442', NULL, NULL, 'PO9000124804' FROM DUAL UNION ALL
SELECT '5758', NULL, NULL, 'PO9000124805' FROM DUAL UNION ALL
SELECT '5988', NULL, NULL, 'PO9000124806' FROM DUAL UNION ALL
SELECT '6748', NULL, NULL, 'PO9000124807' FROM DUAL UNION ALL
SELECT '7123', 'O103654787', NULL, NULL FROM DUAL UNION ALL
SELECT '7124', 'O103214217', NULL, NULL FROM DUAL UNION ALL
SELECT '7125', 'O103215320', NULL, NULL FROM DUAL UNION ALL
SELECT '7126', 'O106212219', NULL, NULL FROM DUAL UNION ALL
SELECT '7125', 'O103215320', NULL, NULL FROM DUAL UNION ALL
SELECT '5855', NULL, 'PL192010120', NULL FROM DUAL UNION ALL
SELECT '9419', NULL, 'PL121122221', NULL FROM DUAL UNION ALL
SELECT '5748', NULL, 'PL272634123', NULL FROM DUAL UNION ALL
SELECT '7055', NULL, 'PL983002032', NULL FROM DUAL UNION ALL
SELECT '9999', NULL, NULL, 'PO9000124806' FROM DUAL UNION ALL
SELECT '1111', NULL, NULL, 'PO9000124806' FROM DUAL
;
对我的 SQLFIDDLE
使用以下查询,我基本上可以获得第一个“级别”:
WITH
-- Use one order as an example
-- This will eventually be used for many orders at once
currOrder AS
(
SELECT
tblInputs.Order_No
FROM
tblInputs
WHERE
Direction = 'PLUS'
AND
(Type = 'Production' OR Type = 'Planned')
-- Added this for example purposes only!
AND
Order_No LIKE '%O103962037%'
),
-- Now get the details about this order being a REQUIREMENT
Req AS
(
SELECT
-- unique identifier(s), unfortunately two fields combine to make the primary key
Req_ID,
Req_No
FROM
Requirements
INNER JOIN currOrder ON currOrder.Order_No = Requirements.Order_No
),
-- This is a giant bridge table of requirements, and replenishments
-- A requirement can be made up of many replenishments, and a replenishment can satisfy many requirements
-- Find the replenishments for our specific requirement
Req_Rep AS
(
SELECT DISTINCT
ReqRep.REP_ID
FROM
ReqRep
INNER JOIN Req ON ReqRep.Req_ID = Req.Req_ID AND ReqRep.Req_No = Req.Req_No
),
-- Now, grab the replenishment data that we care about, and its details
-- Only one field will be filled in at a time depending on what the replenishment type is
Rep AS
(
SELECT DISTINCT
Req_Rep.Rep_ID,
CASE
WHEN Replenishments.Order_No IS NULL AND Replenishments.Planned_No IS NULL THEN Replenishments.Purchase_No
WHEN Replenishments.Order_No IS NULL AND Replenishments.Planned_No IS NOT NULL AND Replenishments.Purchase_No IS NULL THEN Replenishments.Planned_No
WHEN Replenishments.Order_No IS NOT NULL AND Replenishments.Planned_No IS NULL AND Replenishments.Purchase_No IS NULL THEN Replenishments.Order_No
ELSE NULL END AS The_Number
FROM
Req_Rep
INNER JOIN Replenishments on Replenishments.Rep_ID = Req_Rep.Rep_ID
)
-- Grab the results
SELECT DISTINCT * FROM Rep
使用该查询,我得到了这个数据集:
REP_ID THE_NUMBER
7123 O103654787
7125 O103215320
7124 O103214217
7126 O106212219
这表明,对于特定的要求(由其Order_No
指定),这些是满足它的补货。然后,对于这些补货,这是与其关联的元数据。
我现在需要获取The_Number
并基本上重复整个过程。对于生产或计划订单的每个补货,继续查找所有补货(因为,如果补货是生产或计划订单,则可能有额外的补货)
目标数据集如下所示:
| Number | Req_ID | Req_No | Rep_ID | Details | Level |
|:-----------:|:------:|:------:|:------:|:------------:|:-----:|
| O103962037 | BDD | 377 | 7123 | O103654787 | 1 |
| O103962037 | BDD | 377 | 7124 | O103214217 | 1 |
| O103962037 | BDD | 377 | 7125 | O103215320 | 1 |
| O103962037 | BDD | 377 | 7126 | O106212219 | 1 |
| O103654787 | QZX | 96 | 5748 | PL272634123 | 2 |
| O103214217 | NFD | 20 | 7055 | PL983002032 | 2 |
| O103215320 | GBV | 33 | 9999 | PO9000124806 | 2 |
| O106212219 | ERQ | 22 | 7736 | PO9000124799 | 2 |
| PL272634123 | MRP | 99 | 1111 | PO9000124806 | 3 |
| PL983002032 | EWE | 22 | 1111 | PO9000124806 | 3 |
我相信我已经在查询中实现了递归 anchor
,但我无法确定如何构建其余部分。如有任何建议,我们将不胜感激。
我已查看这些帖子:
我认为我需要的行是 Rep.The_Number = Requirements.Order_No
,但我不知道如何定义它。
最佳答案
假设我正确理解了数据模型,我想出了一个解决方案,希望至少可以作为更复杂版本的起点。 SQLFiddle在这儿。我必须修改示例数据,因为我无法根据提供的示例复制您的预期结果。
我想出的 SQL 是这样的:
WITH t as (
SELECT coalesce(r.planned_no, r.Order_No) order_no,
r.Req_ID,
r.Req_No,
rr.REP_ID,
coalesce(rp.purchase_no, rp.planned_no, rp.order_no) details,
0 replevel
FROM requirements r
JOIN ReqRep rr ON rr.Req_ID = r.Req_ID AND rr.Req_No = r.Req_No
JOIN Replenishments rp on rp.Rep_ID = rr.Rep_ID),
det_t (order_no, req_id, req_no, rep_id, details, replevel, rep_path) as (
SELECT t.Order_No,
t.Req_ID,
t.Req_No,
t.REP_ID,
t.details,
1 replevel,
t.order_no rep_path
FROM t
WHERE Order_No LIKE '%O103962037%'
UNION ALL
SELECT t.Order_No,
t.Req_ID,
t.Req_No,
t.REP_ID,
t.details,
d.replevel + 1,
rep_path || '=>' || t.order_no rep_path
FROM det_t d
JOIN t ON t.order_no = d.details
)
select order_no,
req_id,
req_no,
rep_id,
details,
replevel,
rep_path
from det_t
order by replevel, order_no;
执行示例如下:
FSITJA@db01 2019-07-16 09:59:00> WITH t as (
2 SELECT coalesce(r.planned_no, r.Order_No) order_no,
3 r.Req_ID,
4 r.Req_No,
5 rr.REP_ID,
6 coalesce(rp.purchase_no, rp.planned_no, rp.order_no) details,
7 0 replevel
8 FROM requirements r
9 JOIN ReqRep rr ON rr.Req_ID = r.Req_ID AND rr.Req_No = r.Req_No
10 JOIN Replenishments rp on rp.Rep_ID = rr.Rep_ID),
11 det_t (order_no, req_id, req_no, rep_id, details, replevel, rep_path) as (
12 SELECT t.Order_No,
13 t.Req_ID,
14 t.Req_No,
15 t.REP_ID,
16 t.details,
17 1 replevel,
18 t.order_no rep_path
19 FROM t
20 WHERE Order_No LIKE '%O103962037%'
21 UNION ALL
22 SELECT t.Order_No,
23 t.Req_ID,
24 t.Req_No,
25 t.REP_ID,
26 t.details,
27 d.replevel + 1,
28 rep_path || '=>' || t.order_no rep_path
29 FROM det_t d
30 JOIN t ON t.order_no = d.details
31 )
32 select order_no,
33 req_id,
34 req_no,
35 rep_id,
36 details,
37 replevel,
38 rep_path
39 from det_t
40 order by replevel, order_no;
ORDER_NO REQ_ID REQ_NO REP_ID DETAILS REPLEVEL REP_PATH
----------- ------- ------- ------- --------------- ---------- -------------------------------------
O103962037 BDD 37 7123 O103654787 1 O103962037
O103962037 BDD 37 7124 O103214217 1 O103962037
O103962037 BDD 37 7125 O103215320 1 O103962037
O103962037 BDD 37 7126 O106212219 1 O103962037
O103214217 NFD 20 7055 PL191908854 2 O103962037=>O103214217
O103215320 GBV 33 9999 PO9000124806 2 O103962037=>O103215320
O103215320 MRP 11 7736 PO9000124799 2 O103962037=>O103215320
O103654787 QZX 96 5748 PL272634123 2 O103962037=>O103654787
O106212219 ERQ 22 7736 PO9000124799 2 O103962037=>O106212219
PL191908854 EWE 42 7634 PO9000124802 3 O103962037=>O103214217=>PL191908854
PL272634123 XYZ 36 8888 PL2222222222 3 O103962037=>O103654787=>PL272634123
11 rows selected.
我认为样本数据与预期结果不匹配。 根据您的预期结果,除非我误解了数据模型,否则第 3 级行(MRP 和 EWE)REQ_NO 与示例数据中的内容不匹配。
MRP 在预期结果中 Req_No = 99,在插入中 Req_No = 11,将其连接到补货级别 1 Rep_Id = 7125 下的级别 2。
EWE 在预期结果中具有 Req_No = 22,在插入中具有 Req_No = 42,并且它从补充 Rep_Id = 7055 下的级别 1 连接。 然而,在需求表中,EWE 的 Planned_No = 'PL191908854',而在 2 级补货中,Rep_Id = 7055 指向 Order_No = 'PL983002032'。
如果我将 Replinishment Rep_Id = 7055 上提供的示例数据从 Order_No = 'PL983002032' 更改为 'PL191908854',它将在级别 3 下正确显示 EWE。
这是我在补充表插入中更改的内容(反射(reflect)在 SQLFiddle 中): 添加(只是为了说明有效的 3 级连接):
SELECT '8888', NULL, NULL, 'PL2222222222' FROM DUAL
修改(让 EWE 在第 3 级正确显示):
SELECT '7055', NULL, 'PL191908854', NULL FROM DUAL UNION ALL
关于sql - 递归查询设计 - Oracle SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57047104/