2012-04-04 16 views
2

我的框中包含不同大小的相同項目。用於選擇最小數量的框的SQL查詢

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 
        2 4 4 4 2 

我需要什麼盒子支付我的必需品?

我可以用箱00003,00004,00005,00006,這樣一來,我就會聚集:

    S M L XL XXL 
        8 8 8 8 8 

但很多物品會被浪費。

我還可以使用盒00007,00008,並得到:

    S M L XL XXL 
        2 4 4 4 2 

哪個適合我,不過,我必須移動2盒,同時BOX 00009具有正是我需要的,具有minimun努力。

綜上所述,我需要覆蓋我的必需品的最小箱量是多少? 我找不到一個起點來建立一個查詢或某種代碼解決這個問題。任何幫助將不勝感激。

預先感謝您。

+1

聽起來很像[bin裝箱問題](http://en.wikipedia.org/wiki/Bin_packing_problem)。 – 2012-04-04 10:16:01

+0

什麼是您的DBMS?另外,是否有任何性能限制需要滿足? – 2012-04-04 10:58:05

+0

你好, bin包裝問題聽起來很可怕,但也很有趣。我曾經遇到過一些與它有關的問題,所以它對我有用,謝謝kaiz.net。 Branko, 我使用mysql和MS訪問作爲替代前端。沒有限制 – Fran 2012-04-04 11:20:13

回答

0

以下將在SQL-Server上解決您的問題。它通過使用遞歸CTE來確定每個大小的數量全部盒子的組合(對於大量盒子,這可能會變得麻煩並且需要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