编辑:
我被告知让你们阅读意味着我得到的关注较少。我很抱歉。这是一个更简单的版本:
比尔从一家商店获得了价值100美元的物品。他希望退回足够的物品以获得30美元的回报。
商店有一个Point of Return系统,可以帮助他做到这一点。
以下是他扫描物品后的数据:
item ¦ price ¦
socks 4.00
cheap tv 22.00
book on tape 9.00
book on paper 7.00
party hats 3.00
picture frame 10.00
hammer 5.00
juicer 16.00
mysql guide 24.00
total items ¦ total price ¦
9 100.00
Option 1
===============
item ¦ price ¦
cheap tv 22.00
party hats 3.00
hammer 5.00
===============
Option 2
===============
item ¦ price ¦
socks 4.00
picture frame 10.00
juicer 16.00
===============
Option 3
===============
item ¦ price ¦
book on tape 9.00
hammer 5.00
juicer 16.00
我可能错过了一些选项,因为我完成了所有这些。
所以,最大的问题是:
是否有一种方法(可能使用GROUP BY)有一个查询可以返回可能的项目组合?
谢谢!
一
答案 0 :(得分:2)
您要求的所有子集总计最多为30美元。
这听起来很像subset sum problem和knapsack problem,所以我强烈怀疑你可以通过一个简单的查询来做到这一点。你可能不得不求助于T-SQL,但即便如此也可能看起来很难看。
我认为编程是走到这里的方式。
答案 1 :(得分:1)
如果项目数量足够小,您可以使用SQL强制执行此操作。这可能是一个快速编写的解决方案,但您可能希望更聪明地做一些事情。听起来像“knapsack problem”这是NP完整的。
如果项目数量很大,您将需要深入研究动态编程算法。你必须问自己这对你的申请有多重要。
如果物品数量相对较少,您可能会对此进行暴力破解。查找匹配的1,2或3项组合的强制SQL语句(您要求的)如下所示。如果这不令人满意,那么SQL可能不适合这项工作。
SELECT
i1.id AS id1,
NULL AS id2,
NULL AS id3,
i1.amount
FROM
items i1
UNION ALL
SELECT
i1.id AS id1,
i2.id AS id2,
i3.id AS id3,
i1.amount + i2.amount AS total
FROM
items i1,
items i2
WHERE
i1.amount + i2.amount = 30 AND
i1.id <> i2.id AND
i1.id <> i3.id
UNION ALL
SELECT
i1.id AS id1,
i2.id AS id2,
i3.id AS id3,
i1.amount + i2.amount + i3.amount AS total
FROM
items i1,
items i2,
items i3
WHERE
i1.amount + i2.amount + i3.amount = 30 AND
i1.id <> i2.id AND
i1.id <> i3.id AND
i2.id <> i3.id
在Oracle中,您可以使用CUBE函数将其转换为通用版本,不确定MySQL等效项。
答案 2 :(得分:0)
我不认为group by能做到。
我想不出比找到/尝试所有排列更好的方法,无论是使用您选择的编程语言还是使用存储过程。
如果您的物品超过30美元,则可以省略它们。
如果你想通过某些标准选择“最佳”选项,那么会有一些改进。答案 3 :(得分:0)
这个问题实际上是P / NP。例如,你可能找不到最合适的文章价格,没有暴力搜索,如果你的客户存储很大 - 你可以发现搜索非常持久。
你可以使用一些可以给你很好猜测的现有算法,但我担心它们都是非SQL的算法。
我建议您近似解决问题:
创建程序/查询,找到最适合所需价格的一篇文章,然后再次调用它以获得新的更改。不完美,但会完成这项工作。