2012-04-04 11 views
2

異なるサイズの同じアイテムを含むボックスがあります。私は私の必需品をカバーする必要がありますどのようなボックス最小のボックス数を選択するSQLクエリ

    S M L XL XXL 
        2 4 4 4 2 

Boxes    S M L XL XXL 

00001    2 4 4  
00002       4 2 
00003    8    
00004     8   
00005      8 8 
00006        8 
00007    1 2 2 2 2 
00008    1 2 2 2 
00009    2 4 4 4 2 
00010    3 5 4 4 2 
00011    2 3 4 4 2 

は今、私はこのサイズのモデルを取得する必要がありますか?

    S M L XL XXL 
        8 8 8 8 8 

のが、アイテムの多くは無駄になる:

私は箱00003、00004、00005、00006、この方法を使用することができ、私が集まるでしょう。

私もボックス00007、00008を使用して得ることができる:私に合う

    S M L XL XXL 
        2 4 4 4 2 

を、それでも、私はその間BOXの00009私はminimun努力で、必要な正確に何を持って、2箱を移動する必要があります。

要約すると、私は自分の必需品をカバーするために必要なボックスの最小量は何ですか? クエリを作成するための開始点や、ある種のコードを見つけることができません。どんな助けもありがとう。

ありがとうございます。

+1

[ビン充填問題](http://ja.wikipedia.org/wiki/Bin_packing_problem)とよく似ています。 –

+0

DBMSとは何ですか?また、満たす必要のあるパフォーマンス上の制約はありますか? –

+0

こんにちは、 ビンの梱包の問題は恐ろしく聞こえますが面白いです。私はそれに関連する過去のいくつかの問題に直面していたので、それは私のために役立つだろう、ありがとうkaiz.net。 Branko、 私はmysqlとMSアクセスを代替フロントエンドとして使用します。制限なし – Fran

答えて

0

次は、SQLサーバー上で問題を解決するために動作します。これは再帰CTEを使用して、ALLボックスの組み合わせの各サイズの数を決定することによって動作します(大量のボックスの場合、これは煩雑になり、MAXRECURSIONを変更する必要があります)。次に、これらの組み合わせのどれが各サイズの最小数の基準を満たしているかを判断し、残りの組み合わせを必要な数の順にランク付けし、次に最小基準を満たすために無駄にした総数をランク付けします。 RANK()関数で注文を変更すると、ソリューションのランク付け方法が変更されます。

DECLARE @S INT = 2, 
     @M INT = 4, 
     @L INT = 4, 
     @XL INT = 4, 
     @XXL INT = 2 


CREATE TABLE #Boxes (Model VARCHAR(5), S INT, M INT, L INT, XL INT, XXL INT) 
INSERT #Boxes VALUES 
    ('00001', 2, 4, 4, 0, 0), 
    ('00002', 0, 0, 0, 4, 2), 
    ('00003', 8, 0, 0, 0, 0), 
    ('00004', 0, 8, 0, 0, 0), 
    ('00005', 2, 0, 8, 8, 0), 
    ('00006', 2, 0, 0, 0, 8), 
    ('00007', 1, 2, 2, 2, 2), 
    ('00008', 1, 2, 2, 2, 0), 
    ('00009', 2, 4, 4, 4, 2), 
    ('00010', 3, 5, 4, 4, 2), 
    ('00011', 2, 3, 4, 4, 2) 

;WITH CTE AS 
( SELECT *, CONVERT(VARCHAR(1000), Model + ';') [Models], 1 [Boxes] 
    FROM #Boxes 
    UNION ALL 
    SELECT a.Model, 
      a.S + b.S, 
      a.M + b.M, 
      a.L + b.L, 
      a.XL + b.XL, 
      a.XXL + b.XXL, 
      CONVERT(VARCHAR(1000), b.Models + a.Model + ';'), 
      Boxes + 1 
    FROM #Boxes a 
      INNER JOIN CTE b 
       ON a.Model > b.Model 
), CTE2 AS 
( SELECT Models, 
      S, 
      M, 
      L, 
      XL, 
      XXL, 
      Boxes, 
      (S + M + L + XL + XXL) - (@S + @M + @L + @XL + @XXL) [Wasted] 
    FROM CTE 
    WHERE S >= @S 
    AND  M >= @M 
    AND  L >= @L 
    AND  XL >= @XL 
    AND  XXL >= @XXL 
) 
SELECT *, 
     RANK() OVER(ORDER BY Boxes, Wasted) [Rank] 
FROM CTE2 

DROP TABLE #Boxes 
関連する問題