オーダーの品目があり、そのうちのいくつかは1 つ購入すると 1 つ無料で提供されています。このビジネス ロジックは次のとおりです。
- ペアの最も安いアイテムは無料です
- お客様にとって最良の取引が選択されます
- アイテムがオファーで使用されると、再度使用することはできません
OrderItemID
以下は、すべてのオファーに結合されたラインアイテム ( ) の例です。
╔═════════════╦═════════╦═══════╗
║ OrderItemID ║ OfferID ║ Value ║
╠═════════════╬═════════╬═══════╣
║ 1 ║ 1 ║ 22.50 ║
║ 2 ║ 1 ║ 25.00 ║
║ 3 ║ 2 ║ 14.99 ║
║ 4 ║ 1 ║ 5.00 ║
║ 5 ║ 1 ║ 7.00 ║
║ 5 ║ 2 ║ 7.00 ║
║ 5 ║ 3 ║ 7.00 ║
║ 6 ║ 3 ║ 7.50 ║
╚═════════════╩═════════╩═══════╝
これから、上記のルールを使用して有効な組み合わせの完全なセットを、節約 (つまり、2 番目のアイテムの価格) で並べ替えて導き出すことができます。
╔═════════════════╦═════════════════╦═════════╦═══════╦════════╗
║ PaidOrderItemID ║ FreeOrderItemID ║ OfferID ║ Price ║ Saving ║
╠═════════════════╬═════════════════╬═════════╬═══════╬════════╣
║ 2 ║ 1 ║ 1 ║ 25.00 ║ 22.50 ║
║ 1 ║ 5 ║ 1 ║ 22.50 ║ 7.00 ║
║ 2 ║ 5 ║ 1 ║ 25.00 ║ 7.00 ║
║ 3 ║ 5 ║ 2 ║ 14.99 ║ 7.00 ║
║ 6 ║ 5 ║ 3 ║ 7.50 ║ 7.00 ║
║ 1 ║ 4 ║ 1 ║ 22.50 ║ 5.00 ║
║ 2 ║ 4 ║ 1 ║ 25.00 ║ 5.00 ║
║ 5 ║ 4 ║ 1 ║ 7.00 ║ 5.00 ║
╚═════════════════╩═════════════════╩═════════╩═══════╩════════╝
注文項目に重複することなく、組み合わせを抽出したいと思います。次の表は、私が必要なものを示しています
╔═════════════════╦═════════════════╦═════════╦═══════╦════════╗
║ PaidOrderItemID ║ FreeOrderItemID ║ OfferID ║ Price ║ Saving ║
╠═════════════════╬═════════════════╬═════════╬═══════╬════════╣
║ 2 ║ 1 ║ 1 ║ 25.00 ║ 22.50 ║
║ 3 ║ 5 ║ 2 ║ 14.99 ║ 7.00 ║
╚═════════════════╩═════════════════╩═════════╩═══════╩════════╝
最初の行は、節約額が最も高い行です。次の行は、最初の行で使用されているPaidOrderItemID
とFreeOrderItemID
が異なる最初の行です。ItemID
カーソルを使用して一番上の行を一時テーブルに抽出し、同じOrderItemID
s を使用してオファーを削除し、オファーがなくなるまで繰り返します。
セットベースの方法を使用してそれを行う方法があるかどうか知りたいですか? 再帰的な CTE アプローチを使用してみましたが、うまくいきませんでした。コードは SQL Server 2008 R2 で実行する必要があります。
この例のコードは次のとおりです。
DECLARE @orderItemOffers TABLE (OrderItemID INT, OfferID INT, Value MONEY)
INSERT INTO @orderItemOffers
(OrderItemID, OfferID, Value)
VALUES (1, 1, 22.50),
(2, 1, 25.00),
(3, 2, 14.99),
(4, 1, 5.00),
(5, 1, 7.00),
(5, 2, 7.00),
(5, 3, 7.00),
(6, 3, 7.50)
SELECT * FROM @orderItemOffers
DECLARE @offerCombos TABLE (
PaidOrderItemID INT,
FreeOrderItemID INT,
OfferID INT,
Price MONEY,
Saving MONEY
)
INSERT INTO @offerCombos (
PaidOrderItemID,
FreeOrderItemID,
OfferID,
Price,
Saving
)
SELECT PaidItem.OrderItemID,
FreeItem.OrderItemID,
FreeItem.OfferID,
PaidItem.Value,
FreeItem.Value
FROM @orderItemOffers PaidItem
INNER JOIN @orderItemOffers FreeItem
ON FreeItem.OrderItemID <> PaidItem.OrderItemID
AND FreeItem.OfferID = PaidItem.OfferID
AND (FreeItem.Value < PaidItem.Value
OR (FreeItem.Value = PaidItem.Value
AND FreeItem.OrderItemID > PaidItem.OrderItemID
)
)
ORDER BY FreeItem.Value DESC
SELECT * FROM @offerCombos
DECLARE @takenOffers TABLE (
PaidOrderItemID INT,
FreeOrderItemID INT,
OfferID INT,
Price MONEY,
Saving MONEY
)
DECLARE offerCursor CURSOR FAST_FORWARD FOR SELECT * FROM @offerCombos
OPEN offerCursor
DECLARE @PaidOrderItemID INT, @FreeOrderItemID INT,
@OfferID INT, @Price MONEY, @Saving MONEY
FETCH NEXT FROM offerCursor
INTO @PaidOrderItemID, @FreeOrderItemID, @OfferID, @Price, @Saving
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO @takenOffers
(PaidOrderItemID, FreeOrderItemID, OfferID, Price, Saving)
VALUES (@PaidOrderItemID, @FreeOrderItemID, @OfferID, @Price, @Saving)
DELETE FROM @offerCombos
WHERE PaidOrderItemID IN (@PaidOrderItemID, @FreeOrderItemID)
OR FreeOrderItemID IN (@PaidOrderItemID, @FreeOrderItemID)
FETCH NEXT FROM offerCursor
INTO @PaidOrderItemID, @FreeOrderItemID, @OfferID, @Price, @Saving
END
CLOSE offerCursor
DEALLOCATE offerCursor
SELECT * FROM @takenOffers