ここでのタスクは、サプライヤからアイテム (部品) を注文する最適な (以下に詳述する) 方法を定義することです。
テーブル スキーマの関連部分 (いくつかのサンプル データを含む) は次のとおりです。
アイテム
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
決済割引 (パーセンテージ、つまり上記の場合は 2.5% ) です。ID=2
仕入先品目
SUPPLIER_ID ITEM_ID PRICE
1 2 21.67
1 5 45.54
1 7 32.97
これは、サプライヤと、サプライヤがその品目に対して請求する価格 (ドル単位) を使用した、サプライヤと品目との間の多対多の結合です。すべてのアイテムには少なくとも 1 つのサプライヤーがいますが、複数のサプライヤーがいるものもあります。サプライヤにはアイテムがない場合があります。
パーツリクエスト
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
問題は、選択のためにユーザーに提示する必要がある 3 つの最適なソリューションがある各「場所」に対してこれらのパーツを注文する最適な方法は何かということです。
- 仕入先が最も少ない注文の組み合わせ
- 合計コストが最も低い注文の組み合わせ。つまり
QUANTITY*PRICE
、各アイテムの合計と、DELIVERY
無視したすべての注文を合計した各注文の合計DISCOUNT
- 項目 2 と同じですが、
DISCOUNT
明らかに、利用可能な注文の組み合わせを決定する必要があり、最適なものを決定することは簡単ですが、組み合わせを構築するための効率的な方法に少しこだわっています。
ランダム データを使用して、SQL Server 2008 でいくつかの SQL フィドルを作成しました。これには、100 個のアイテム、10 個のサプライヤー、および 100 個の要求があります。これには、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 を使用してサプライヤーを 1 つずつ削除し、まだすべてのアイテムをカバーしている場合は追加することです。SOLUTION_ID は、削除されたサプライヤーの CSV リストであり、一部は各ソリューションを一意に識別し、一部はチェックするため、順列ではなく組み合わせを取得します。
まだ詳細に取り組んでいますが、この更新の目的は、コミュニティが「やった、それはうまくいくようです」または代わりに「ばか、それはうまくいかない...」と言うことができるようにすることでした。
ありがとう