此处的任务是定义供应商订购商品(部件)的最佳方式(详见下文)。
表模式的相关部分(带有一些示例数据)是
项
ID NUMBER
1 Item0001
2 Item0002
3 Item0003
商
ID NAME DELIVERY DISCOUNT
1 Supplier0001 0 0
2 Supplier0002 0 0.025
3 Supplier0003 20 0
DELIVERY
是该供应商在每次交货时征收的运费(以美元计)。 DISCOUNT
是该供应商允许按时付款的结算折扣(以百分比表示,即ID=2
为2.5%)。
SupplierItems
SUPPLIER_ID ITEM_ID PRICE
1 2 21.67
1 5 45.54
1 7 32.97
这是供应商和商品之间的多对多连接,供应商为该商品收取的价格(以美元计)。每个项目至少有一个供应商,但有些供应商不止一个。供应商可能没有物品。
PartsRequests
ID ITEM_ID QUANTITY LOCATION_ID ORDER_ID
1 59 4 2 (null)
2 89 5 2 (null)
3 42 4 2 (null)
此表是来自现场站点的请求,供供应商订购和交付给该站点的部件。向网站交付任意数量的商品会收取运费。订购部件后,ORDER_ID
会插入到表格中,因此我们只关注那些ORDER_ID IS NULL
问题是,为每个“LOCATION”订购这些零件的最佳方式是什么,其中有3个最佳解决方案需要呈现给用户以供选择。
QUANTITY*PRICE
加上每个订单的DELIVERY
总和忽略DISCOUNT
的所有订单DISCOUNT
显然,我需要确定可用订单的组合,然后确定最佳订单的组合变得微不足道,但我有点坚持以有效的方式来处理构建组合。
我在SQL Server 2008中使用随机数据构建了一些SQL小提琴。 This one有100个项目,10个供应商和100个请求。 This one有1000个项目,50个供应商和250个请求。表模式是相同的。
更新
我推断解决方案必须是递归的,我构建了一个很好的表值函数来获取但是我在SQL Server中遇到了递归的32个硬限制。无论如何我对它感到不舒服,因为它暗示了一种程序性语言解决方案而不是RDMS。
所以我现在正在玩CTE递归。
根查询是:
SELECT DISTINCT
'' SOLUTION_ID
,LOCATION_ID
,SUPPLIER_ID
,(subquery I haven't quite worked out) SOLE_SUPPLIER
FROM PartsRequests pr
INNER JOIN
SupplierItems si ON pr.ITEM_ID=si.ITEM_ID
WHERE pr.ORDER_ID IS NULL
这使得所有能够提供所需物品的供应商肯定是一种解决方案,可能并非最佳。如果供应商是该位置所需的任何产品的唯一供应商,则子查询设置标记;如果是这样,他们必须成为任何解决方案的一部分。
递归部分是通过CTE.SUPPLIER_ID<> CTE.SUPPLIER_ID逐个删除供应商,如果它们仍覆盖所有项目,则添加它们。 SOLUTION_ID将是已删除供应商的CSV列表,部分用于唯一标识每个解决方案,部分用于检查,因此我得到组合而不是排列。
仍然致力于细节,这次更新的目的是让社区说“耶,看起来那样会起作用”,或者“你好白痴,那不会起作用,因为......”
由于
答案 0 :(得分:2)
这是一个更通用的答案(如在sql中),因为我认为解决这个问题需要更强大的功能。您的第一个方案是选择最少数量的供应商。这个问题可以看作是set cover problem,因为您试图满足供应商对每个站点的所有需求。这个问题已经完成NP了。
您的第三种情况似乎与第二种情况基本相同。您只需在价格中考虑折扣,假设您按时支付每笔订单。
第二种情况至少是NP难度,因为我发现与facility location problem有很多相似之处。您正在尝试根据价格和交付成本(开放成本)决定使用(开放)哪些供应商(设施)来满足您的订单(需求)。
列举您的可能解决方案似乎不可行,因为有10家供应商,您有2 ^ 10种使用它们的可能性,进一步复杂化内部需求分配。
我建议一些动态编程,首先选择你必须使用的供应商(=他们是唯一提供特定产品的供应商),消除一些可能性(如果供应商A +交付的成本A<成本为供应商B)然后尝试扩展您的可能解决方案集。线性规划也是一种有效的思路。