sql >> データベース >  >> RDS >> Oracle

各製品に適したサイズのボックスを見つけるにはどうすればよいですか?

    もちろん、重要なのは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   
    


    1. SQLFiddleでPL/SQLを取得する方法は?

    2. JPA +StoredProcedureCall+オブジェクトタイプINパラメータ

    3. MySQLビューのリストを取得するにはどうすればよいですか?

    4. DBUtilsがJavaBeanのフィールドへの入力に失敗する