4

オーダーの品目があり、そのうちのいくつかは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   ║
╚═════════════════╩═════════════════╩═════════╩═══════╩════════╝

最初の行は、節約額が最も高い行です。次の行は、最初の行で使用されているPaidOrderItemIDFreeOrderItemIDが異なる最初の行です。ItemID

カーソルを使用して一番上の行を一時テーブルに抽出し、同じOrderItemIDs を使用してオファーを削除し、オファーがなくなるまで繰り返します。

セットベースの方法を使用してそれを行う方法があるかどうか知りたいですか? 再帰的な 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
4

2 に答える 2

0

これはどうですか?

SELECT *, (ROW_NUMBER() OVER(PARTITION BY OfferID ORDER BY Value DESC, OrderItemID) - 1) % 2 IsFree
FROM @orderItemOffers

オファー内で、アイテムに値の降順で番号を付けます。それが次に高い値であるため、他のすべてのアイテムは無料です。

于 2014-03-05T23:00:07.303 に答える
0

このようなものから始めることができます

WITH Offer AS (
SELECT *, rn=ROW_NUMBER() OVER (PARTITION BY OfferID ORDER BY Value DESC)
FROM @orderItemOffers
)
SELECT 
    o1.OrderItemID AS PaidOrderItemID 
    ,o2.OrderItemID AS FreeOrderItemID
    ,o1.OfferID
    ,o1.Value AS Price
    , o2.Value as Saving
FROM Offer o1
LEFT JOIN Offer o2 
    ON o1.OfferID = o2.OfferID
    AND o1.rn = o2.rn -1
WHERE o1.rn % 2 = 1
ORDER BY OfferID,PaidOrderItemID

sql fiddle demo

于 2013-10-29T13:31:40.753 に答える