我有订单中的订单项,其中一些是买一送一优惠。其业务逻辑是:
以下是一些订单项(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 ║
╚═════════════╩═════════╩═══════╝
从这里我可以使用上面的规则得出完整的有效组合,按照保存(即第二项的价格)排序:
╔═════════════════╦═════════════════╦═════════╦═══════╦════════╗
║ 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
删除商品,重复直到没有商品剩余。
我想知道是否有办法可以使用基于集合的方法完成?我尝试过使用递归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
答案 0 :(得分: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 强> 的
答案 1 :(得分:0)
这个怎么样?
SELECT *, (ROW_NUMBER() OVER(PARTITION BY OfferID ORDER BY Value DESC, OrderItemID) - 1) % 2 IsFree
FROM @orderItemOffers
在要约中,按值按降序对项目进行编号;所有其他项目都是免费的,因为它是下一个最高价值。