もちろん、重要なのは2つのテーブル間の結合です。理解を助けるために、完全なクエリではなく、最初に個別に表示します。アイテムごとに、アイテムを収容できるすべてのボックスサイズが見つかります。
すべての場合において、製品の高さ<=ボックスの高さ、および他の2つの次元がいずれかの順列で適合する場合、一致は可能です(製品は常に回転できます) 敷設可能かどうかに関係なく、ボックスに収まるようにします。
敷設可能な製品の場合のみ、ボックスに収まるように製品を3次元すべてで回転させることができます。つまり、敷設可能な製品の場合のみ、製品の幅または奥行きをボックスの高さと比較し、製品の残りの2つの寸法をボックスの幅と奥行きと比較できます。
私が今言ったことを理解すると(コンピューターなしで、紙に鉛筆を使ってこれを行う方法として)、コードへの変換はほぼ自動的に行われます:
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に割り当てる関数。集計クエリは、各製品で機能する「最初の」サイズを見つけます。
ここで重要なことは、3つの次元すべてが昇順であるとは限らない場合でも、クエリを任意の数の可能な「ボックスサイズ」に簡単に一般化できることです。 (1つの寸法だけが非常に大きく、他の寸法が小さいボックスなどもあります)。ボックスのボリュームで注文することも、ボックステーブルに保存することもできます。 decode()
を使用したクエリで行うのと同じ優先順位。 機能。
結局、クエリと出力は次のようになります。 nvl()
を使用したことに注意してください select
で '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