给定架构:
create table containers (
id int primary key,
name text,
product_id int,
lot int,
qty int,
parent_id int);
create table orders_items (
id int,
position int,
container_id int);
Wherecontainers
是一个层数未知的层级表。
containers.parent_id = containers.id OR null
一个容器可以容纳其他容器,这是一个容器树结构:
23 Box 40 Parent [ID: NULL, Lot: NULL, Qty: SUM(20+20)=40]
|
|--22 Bag 20 [Parent ID: 23, Lot: NULL, Qty: SUM(10+10)=20]
| |--21 Bag 10 [Parent ID: 22, Lot: 701, Qty: 10]
| |--22 Bag 10 [Parent ID: 22, Lot: 703, Qty: 10]
|
|--19 Bag 20 [Parent ID: 23, Lot: NULL, Qty: SUM(10+10)=20]
|--17 Bag 10 [Parent ID: 19, Lot: 700, Qty: 10]
|--18 Bag 10 [Parent ID: 19, Lot: 701, Qty: 10]
对我们来说,一个集装箱被视为一个远征单位,根据客户要求,一个集装箱可以是一个简单的 10 件塑料袋,也可以是一个完整的托盘,有 10 箱,每箱 5000 件。只有最后一层的容器有批次分配,父容器可以容纳不同的批次,但始终属于同一产品。
我们需要按批次列出单个订单中包含的所有产品。
- 不同的产品不能有相同的批次。
- 一个容器只能装同一产品的容器。
样本数据:
insert into containers values
(23, 'Box 40', 2, null, 40, null)
, (16, 'Pallet', 1, null, 120, null)
, (12, 'Bag 20', 1, null, 20, 14)
, (13, 'Bag 20', 1, null, 20, 14)
, (14, 'Box 40', 1, null, 40, 16)
, (19, 'Bag 20', 2, null, 20, 23)
, (22, 'Bag 20', 2, null, 20, 23)
, (5, 'Bag 20', 1, null, 20, 7)
, (6, 'Bag 20', 1, null, 20, 7)
, (7, 'Box 40', 1, null, 40, 16)
, (1, 'Bag 10', 1, 500, 10, 5)
, (2, 'Bag 10', 1, 501, 10, 5)
, (3, 'Bag 10', 1, 502, 10, 6)
, (4, 'Bag 10', 1, 500, 10, 6)
, (8, 'Bag 10', 1, 600, 10, 12)
, (9, 'Bag 10', 1, 601, 10, 12)
, (10, 'Bag 10', 1, 502, 10, 13)
, (11, 'Bag 10', 1, 501, 10, 13)
, (15, 'Box 40', 1, 600, 40, 16)
, (17, 'Bag 10', 2, 700, 10, 19)
, (18, 'Bag 10', 2, 701, 10, 19)
, (20, 'Bag 10', 2, 703, 10, 22)
, (21, 'Bag 10', 2, 701, 10, 22);
insert into orders_items values
(1, 1, 16),
(1, 2, 23);
订单号1
有两个详细信息行,容器16
& 23
,我需要获取这些容器中包含的所有批次。
在此示例中,结果应显示以下行:
+----+------------+-------------+------+------+------------+
| id | name | product_id | lot | qty | parent_id |
+----+------------+-------------+------+------+------------+
| 1 | 'Bag 10' | 1 | 500 | 10 | 5 |
| 2 | 'Bag 10' | 1 | 501 | 10 | 5 |
| 3 | 'Bag 10' | 1 | 502 | 10 | 6 |
| 4 | 'Bag 10' | 1 | 500 | 10 | 6 |
| 8 | 'Bag 10' | 1 | 600 | 10 | 12 |
| 9 | 'Bag 10' | 1 | 601 | 10 | 12 |
| 10 | 'Bag 10' | 1 | 502 | 10 | 13 |
| 11 | 'Bag 10' | 1 | 501 | 10 | 13 |
| 15 | 'Box 40' | 1 | 600 | 40 | 16 |
| 17 | 'Bag 10' | 2 | 700 | 10 | 19 |
| 18 | 'Bag 10' | 2 | 701 | 10 | 19 |
| 20 | 'Bag 10' | 2 | 703 | 10 | 22 |
| 21 | 'Bag 10' | 2 | 701 | 10 | 22 |
+----+------------+-------------+------+------+------------+
按批次分组:
|----------|---------|-----|----------|
| Order ID | Product | Lot | Quantity |
|----------|---------|-----|----------|
| 1 | 1 | 500 | 20 |
| 1 | 1 | 501 | 20 |
| 1 | 1 | 502 | 20 |
| 1 | 1 | 600 | 50 |
| 1 | 1 | 601 | 10 |
| 1 | 2 | 700 | 10 |
| 1 | 2 | 701 | 20 |
| 1 | 2 | 703 | 10 |
|----------|---------|-----|----------|
我用这个值创建了一个rextester示例。
此代码显示如何使用递归 CTE 返回您要查找的结果。
插入示例数据:
这是递归 CTE:
结果:
从上面的代码可以看出,我已经重命名了一些列以更清楚地反映它们的内容,并添加了一些小的格式以及外键引用。
db<>在这里摆弄