如何为每种产品找到合适尺寸的包装盒?
How can I find the right size box for each product?
很抱歉重新上传这个问题,但我真的很想知道答案。
请允许我再次提出这个问题,希望您的支持。
问题是找到合适尺寸的盒子,让物流商家在发货时省钱。
我们有 2 个 table 是盒子和产品。
Boxes table 包含每个盒子的每个 ID 和尺寸。
'w' 表示宽度,'d' 表示深度,'h' 表示高度。为方便起见,请假设我们只有 3 盒样品。
产品 table 还包括产品 ID、尺寸。尺寸与框 table 的含义相同。
'layable'表示产品不仅可以直立包装,还可以平放包装。例如产品 'g' 是一个易碎的瓶子,不能水平放置在盒子里。因此,这是可放置列中的 'n'。
这道题需要查询每一个商品ID,箱子大小合适。
正确尺寸的盒子意味着产品需要使用最少 space.
的盒子运送
希望您的帮助。谢谢
盒数:
BOX_SIZE
W
D
H
S
353
250
25
M
450
350
160
L
610
460
460
产品:
ID
W
D
H
LAYABLE
a
350
250
25
y
b
450
250
160
y
c
510
450
450
y
d
350
250
25
y
e
550
350
160
y
f
410
400
430
n
g
350
240
25
n
h
450
350
160
n
i
310
360
430
n
j
500
500
600
y
预期输出:
ID
BOX_SIZE
a
S
b
M
...
....
...
....
...
....
g
S
h
M
i
L
j
not available
用于创建和填充 table 进行测试的语句:
create table boxes
( box_size char(1) primary key
, w number not null
, d number not null
, h number not null
)
;
insert into boxes (box_size, w, d, h) values ('S', 353, 250, 25);
insert into boxes (box_size, w, d, h) values ('M', 450, 350, 160);
insert into boxes (box_size, w, d, h) values ('L', 610, 460, 460);
create table products
( id varchar2(10) primary key
, w number not null
, d number not null
, h number not null
, layable char(1) check(layable in ('y', 'n'))
)
;
insert into products (id, w, d, h, layable) values ('a', 350, 250, 25, 'y');
insert into products (id, w, d, h, layable) values ('b', 450, 250, 160, 'y');
insert into products (id, w, d, h, layable) values ('c', 510, 450, 450, 'y');
insert into products (id, w, d, h, layable) values ('d', 350, 250, 25, 'y');
insert into products (id, w, d, h, layable) values ('e', 550, 350, 160, 'y');
insert into products (id, w, d, h, layable) values ('f', 410, 400, 430, 'n');
insert into products (id, w, d, h, layable) values ('g', 350, 240, 25, 'n');
insert into products (id, w, d, h, layable) values ('h', 450, 350, 160, 'n');
insert into products (id, w, d, h, layable) values ('i', 310, 360, 430, 'n');
insert into products (id, w, d, h, layable) values ('j', 500, 500, 600, 'y');
commit;
到目前为止,我可以得出自己的答案,如下所示,但这似乎每个产品 ID 都有三行。因此,这需要过滤到每个查询的最小框。我厌倦了使用 min(function) 但这会导致错误。
select p.id, p.h, p.w, p.d, p.layable, case
when p.layable = 'n' then case
when p.h <= b.h and
((greatest(p.w, p.d ) <= greatest(b.w, b.d))
and (least(p.w, p.d) <= least(b.w, b.d))) then b.id
else 'no' end
when p.layable = 'y' then case
when (p.h + p.w + p.d) <= (b.h + b.w + b.d) and
((greatest(p.h, p.w, p.d) <= greatest(b.h, b.w, b.d))
and (least(p.h, p.w, p.d) <= least(b.h, b.w, b.d))) then b.id
else 'no' end
else 'not available' end
from products p, boxes b
order by p.id;
关键当然是两个table之间的连接。我先单独展示它,而不是完整的查询,以帮助理解。对于每个项目,我们找到可以容纳该项目的所有盒子尺寸。
在所有情况下,如果产品高度 <= 盒子高度,并且其他两个尺寸适合,在任一排列中都可以匹配(产品始终可以 旋转 以适合盒子,无论它们是否可放置)。
仅对于可放置的产品,我们可以在所有三个维度上旋转产品以将其放入盒子中。这意味着,仅对于可放置产品,我们可以将产品宽度或深度与盒子高度进行比较,并将产品的剩余两个尺寸与盒子宽度和深度进行比较。
一旦我们理解了我刚才说的内容(就像我们在没有计算机的情况下,只用铅笔在纸上做的那样),翻译成代码几乎是自动的:
select p.id, b.box_size
from products p left outer join boxes b
on
p.h <= b.h and least (p.w, p.d) <= least (b.w, b.d)
and greatest(p.w, p.d) <= greatest(b.w, b.d)
or
p.layable = 'y'
and
( p.w <= b.h and least (p.h, p.d) <= least (b.w, b.d)
and greatest(p.h, p.d) <= greatest(b.w, b.d)
or
p.d <= b.h and least (p.w, p.h) <= least (b.w, b.d)
and greatest(p.w, p.h) <= greatest(b.w, b.d)
)
;
输出:
ID BOX_SIZE
--- --------
a S
a M
a L
b M
b L
c L
d S
d M
d L
e L
f L
g S
g M
g L
h M
h L
i L
j
对于每个产品,我们都找到了所有合适的尺寸。
注意查询中的外连接,以包含不适合任何框尺寸的产品;出现在输出末尾的产品 j
就是这种情况。请注意,我使用 null
作为“不可用”的标记 - “不可用”一词在null
.
的简单使用
下一步是简单的聚合 - 对于每个产品,找到可行的最小尺寸。最好的工具是 FIRST
聚合函数(如下所用)。我们必须按盒子尺寸订购;由于大小是 S、M、L(只是偶然按字母顺序倒序排列),我使用 decode()
函数将 1 分配给 S,2 分配给 M,3 分配给 L。聚合查询找到“第一个“适用于每个产品的尺寸。
这里重要的是查询可以很容易地推广到任意数量的可能的“框大小”——即使不是所有三个维度都按递增顺序排列。 (你也可以有只有一个尺寸非常大而其他尺寸很小的盒子,等等)。您可以按箱量订购,也可以在箱子table中存储一个偏好顺序,相当于我在查询中使用decode()
函数所做的.
最终,查询和输出如下所示。请注意,我在 select
子句中使用 nvl()
为最后一项生成 'not available'
,以防万一您确实需要它(我对此表示怀疑,但这不是我的业务问题。)
select p.id,
nvl( min(b.box_size) keep (dense_rank first
order by decode(b.box_size, 'S', 1, 'M', 2, 'L', 3))
, 'not available') as box_size
from products p left outer join boxes b
on
p.h <= b.h and least (p.w, p.d) <= least (b.w, b.d)
and greatest(p.w, p.d) <= greatest(b.w, b.d)
or
p.layable = 'y'
and
( p.w <= b.h and least (p.h, p.d) <= least (b.w, b.d)
and greatest(p.h, p.d) <= greatest(b.w, b.d)
or
p.d <= b.h and least (p.w, p.h) <= least (b.w, b.d)
and greatest(p.w, p.h) <= greatest(b.w, b.d)
)
group by p.id
;
ID BOX_SIZE
--- --------
a S
b M
c L
d S
e L
f L
g S
h M
i L
j not available
很抱歉重新上传这个问题,但我真的很想知道答案。
请允许我再次提出这个问题,希望您的支持。
问题是找到合适尺寸的盒子,让物流商家在发货时省钱。
我们有 2 个 table 是盒子和产品。
Boxes table 包含每个盒子的每个 ID 和尺寸。 'w' 表示宽度,'d' 表示深度,'h' 表示高度。为方便起见,请假设我们只有 3 盒样品。
产品 table 还包括产品 ID、尺寸。尺寸与框 table 的含义相同。 'layable'表示产品不仅可以直立包装,还可以平放包装。例如产品 'g' 是一个易碎的瓶子,不能水平放置在盒子里。因此,这是可放置列中的 'n'。
这道题需要查询每一个商品ID,箱子大小合适。 正确尺寸的盒子意味着产品需要使用最少 space.
的盒子运送希望您的帮助。谢谢
盒数:
BOX_SIZE | W | D | H |
---|---|---|---|
S | 353 | 250 | 25 |
M | 450 | 350 | 160 |
L | 610 | 460 | 460 |
产品:
ID | W | D | H | LAYABLE |
---|---|---|---|---|
a | 350 | 250 | 25 | y |
b | 450 | 250 | 160 | y |
c | 510 | 450 | 450 | y |
d | 350 | 250 | 25 | y |
e | 550 | 350 | 160 | y |
f | 410 | 400 | 430 | n |
g | 350 | 240 | 25 | n |
h | 450 | 350 | 160 | n |
i | 310 | 360 | 430 | n |
j | 500 | 500 | 600 | y |
预期输出:
ID | BOX_SIZE |
---|---|
a | S |
b | M |
... | .... |
... | .... |
... | .... |
g | S |
h | M |
i | L |
j | not available |
用于创建和填充 table 进行测试的语句:
create table boxes
( box_size char(1) primary key
, w number not null
, d number not null
, h number not null
)
;
insert into boxes (box_size, w, d, h) values ('S', 353, 250, 25);
insert into boxes (box_size, w, d, h) values ('M', 450, 350, 160);
insert into boxes (box_size, w, d, h) values ('L', 610, 460, 460);
create table products
( id varchar2(10) primary key
, w number not null
, d number not null
, h number not null
, layable char(1) check(layable in ('y', 'n'))
)
;
insert into products (id, w, d, h, layable) values ('a', 350, 250, 25, 'y');
insert into products (id, w, d, h, layable) values ('b', 450, 250, 160, 'y');
insert into products (id, w, d, h, layable) values ('c', 510, 450, 450, 'y');
insert into products (id, w, d, h, layable) values ('d', 350, 250, 25, 'y');
insert into products (id, w, d, h, layable) values ('e', 550, 350, 160, 'y');
insert into products (id, w, d, h, layable) values ('f', 410, 400, 430, 'n');
insert into products (id, w, d, h, layable) values ('g', 350, 240, 25, 'n');
insert into products (id, w, d, h, layable) values ('h', 450, 350, 160, 'n');
insert into products (id, w, d, h, layable) values ('i', 310, 360, 430, 'n');
insert into products (id, w, d, h, layable) values ('j', 500, 500, 600, 'y');
commit;
到目前为止,我可以得出自己的答案,如下所示,但这似乎每个产品 ID 都有三行。因此,这需要过滤到每个查询的最小框。我厌倦了使用 min(function) 但这会导致错误。
select p.id, p.h, p.w, p.d, p.layable, case
when p.layable = 'n' then case
when p.h <= b.h and
((greatest(p.w, p.d ) <= greatest(b.w, b.d))
and (least(p.w, p.d) <= least(b.w, b.d))) then b.id
else 'no' end
when p.layable = 'y' then case
when (p.h + p.w + p.d) <= (b.h + b.w + b.d) and
((greatest(p.h, p.w, p.d) <= greatest(b.h, b.w, b.d))
and (least(p.h, p.w, p.d) <= least(b.h, b.w, b.d))) then b.id
else 'no' end
else 'not available' end
from products p, boxes b
order by p.id;
关键当然是两个table之间的连接。我先单独展示它,而不是完整的查询,以帮助理解。对于每个项目,我们找到可以容纳该项目的所有盒子尺寸。
在所有情况下,如果产品高度 <= 盒子高度,并且其他两个尺寸适合,在任一排列中都可以匹配(产品始终可以 旋转 以适合盒子,无论它们是否可放置)。
仅对于可放置的产品,我们可以在所有三个维度上旋转产品以将其放入盒子中。这意味着,仅对于可放置产品,我们可以将产品宽度或深度与盒子高度进行比较,并将产品的剩余两个尺寸与盒子宽度和深度进行比较。
一旦我们理解了我刚才说的内容(就像我们在没有计算机的情况下,只用铅笔在纸上做的那样),翻译成代码几乎是自动的:
select p.id, b.box_size
from products p left outer join boxes b
on
p.h <= b.h and least (p.w, p.d) <= least (b.w, b.d)
and greatest(p.w, p.d) <= greatest(b.w, b.d)
or
p.layable = 'y'
and
( p.w <= b.h and least (p.h, p.d) <= least (b.w, b.d)
and greatest(p.h, p.d) <= greatest(b.w, b.d)
or
p.d <= b.h and least (p.w, p.h) <= least (b.w, b.d)
and greatest(p.w, p.h) <= greatest(b.w, b.d)
)
;
输出:
ID BOX_SIZE
--- --------
a S
a M
a L
b M
b L
c L
d S
d M
d L
e L
f L
g S
g M
g L
h M
h L
i L
j
对于每个产品,我们都找到了所有合适的尺寸。
注意查询中的外连接,以包含不适合任何框尺寸的产品;出现在输出末尾的产品 j
就是这种情况。请注意,我使用 null
作为“不可用”的标记 - “不可用”一词在null
.
下一步是简单的聚合 - 对于每个产品,找到可行的最小尺寸。最好的工具是 FIRST
聚合函数(如下所用)。我们必须按盒子尺寸订购;由于大小是 S、M、L(只是偶然按字母顺序倒序排列),我使用 decode()
函数将 1 分配给 S,2 分配给 M,3 分配给 L。聚合查询找到“第一个“适用于每个产品的尺寸。
这里重要的是查询可以很容易地推广到任意数量的可能的“框大小”——即使不是所有三个维度都按递增顺序排列。 (你也可以有只有一个尺寸非常大而其他尺寸很小的盒子,等等)。您可以按箱量订购,也可以在箱子table中存储一个偏好顺序,相当于我在查询中使用decode()
函数所做的.
最终,查询和输出如下所示。请注意,我在 select
子句中使用 nvl()
为最后一项生成 'not available'
,以防万一您确实需要它(我对此表示怀疑,但这不是我的业务问题。)
select p.id,
nvl( min(b.box_size) keep (dense_rank first
order by decode(b.box_size, 'S', 1, 'M', 2, 'L', 3))
, 'not available') as box_size
from products p left outer join boxes b
on
p.h <= b.h and least (p.w, p.d) <= least (b.w, b.d)
and greatest(p.w, p.d) <= greatest(b.w, b.d)
or
p.layable = 'y'
and
( p.w <= b.h and least (p.h, p.d) <= least (b.w, b.d)
and greatest(p.h, p.d) <= greatest(b.w, b.d)
or
p.d <= b.h and least (p.w, p.h) <= least (b.w, b.d)
and greatest(p.w, p.h) <= greatest(b.w, b.d)
)
group by p.id
;
ID BOX_SIZE
--- --------
a S
b M
c L
d S
e L
f L
g S
h M
i L
j not available