SQL查询选择最小数量的框

时间:2012-04-04 10:08:22

标签: 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正是我需要的,最小化。

总结一下,我需要用最少的箱子来满足我的需求? 我找不到构建查询的起点或某种代码来解决这个问题。任何帮助将不胜感激。

提前谢谢。

1 个答案:

答案 0 :(得分:0)

以下内容适用于SQL-Server以解决您的问题。它的工作原理是使用递归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