我有一个现有的存储过程,它将购物车项目作为单独的行返回,其中一个字段为所述项目的Quantity
。
如果是促销优惠,例如购买2并获得另外2个免费,则同一产品将作为两行返回,每个产品具有单独的价格和数量。在这种情况下,每行有2行,数量为2。
然后,程序会根据库存数量检查每一行,如果需要,可以通过插入更新订单的新表来更改行。通常情况下,每种产品一次有多种商品,但在极少数情况下(通常用于最终产品),库存中的商品数量可能少于购物车总数应该允许的数量。
在这个例子中,我们可以说还剩3个。该程序将正常比较每一行,并查看库存中有3行,而行只查找2.因此,即使我们只有一个空头,每一行都会通过检查。
我遇到的问题是,当每行进行单独比较时,如何保持购物车中有多少件物品的运行总数?我可以为每个插入声明和更新一个int值吗?
编辑示例数据以说明问题:
假设订单号1在3行上返回相同的产品。全价,折扣和免费(可能不是一个现实的情况,但我的老板会要求我考虑的一个)
LineID | ProductID | Price | Quantity | Note
001 | 00001 | 100 | 2 |
002 | 00001 | 50 | 2 |
003 | 00001 | 0 | 2 |
这些行位于临时表item
中,该表由products
连接到产品ProductID
表,如下所示:
ProductID | BasePrice | QuantityAvailable
00001 | 100 | 3
然后使用此查询检查产品:
UPDATE item
SET
note =
CASE WHEN product.quantityAvailable <= 0 THEN 'This item is no longer available'
WHEN item.quantity > product.quantityAvailable THEN 'Not Enough Stock'
WHEN product.quantityAvailable > item.Quantity THEN REPLACE(note, 'Not Enough Stock', '')
ELSE 'Not Enough Stock' END
, quantity =
CASE WHEN product.quantityAvailable < item.Quantity THEN product.quantityAvailable
ELSE item.Quantity END
OUTPUT inserted.ID, deleted.note, inserted.note, deleted.quantity, inserted.quantity,
INTO @modifiedItems
FROM item
INNER JOIN product ON product.ProductID = item.ID
最终目标是更新项目表以反映所有行中可用的最大数量,结果为:
LineID | ProductID | Price | Quantity | Note
001 | 00001 | 100 | 2 |
002 | 00001 | 50 | 1 | Not enough stock
003 | 00001 | 0 | 0 | Not enough stock
编辑2:电子boogaloo
我试图使用局部变量计算一个运行总计,但这似乎直接跳到总值。示例如下:
DECLARE @runningTotalQuantity int = 0
UPDATE item
SET
note =
CASE WHEN product.quantityAvailable <= 0 THEN 'This item is no longer available'
WHEN item.quantity > product.quantityAvailable THEN 'Not Enough Stock'
WHEN product.quantityAvailable > item.Quantity THEN REPLACE(note, 'Not Enough Stock', '')
ELSE 'Not Enough Stock' END
, quantity =
CASE WHEN @runningTotalQuantity != 0 AND @runningTotalQuantity <= ItemLimits.limitedQty AND (@runningTotalQuantity + Item.Quantity) <= ItemLimits.limitedQty then Item.Quantity
WHEN (@runningTotalQuantity + Item.quantity) >= ItemLimits.limitedQty THEN (ItemLimits.limitedQty - @runningTotalQuantity) WHEN product.quantityAvailable < item.Quantity THEN product.quantityAvailable
ELSE item.Quantity END
, @runningTotalQuantity = @runningTotalQuantity + item.Quantity
OUTPUT inserted.ID, deleted.note, inserted.note, deleted.quantity, inserted.quantity,
INTO @modifiedItems
FROM item
INNER JOIN product ON product.ProductID = item.ID
但是这有以下结果:
LineID | ProductID | Price | Quantity | Note
001 | 00001 | 100 | 2 |
002 | 00001 | 50 | 6 |
003 | 00001 | 0 | 6 |
答案 0 :(得分:1)
在SQL Server 2014中计算运行总计很容易,只需使用SUM() OVER (...)
即可。结果的排序对于运行总计很重要,我使用LineID
来排序行。您可以选择其他适合您的订购。
下面查询中的第一个CTE计算每个产品的运行总计,差异DiffQuantity
告诉我们产品耗尽的行。
Quantity
的新值是三种可能性之一:
1)如果库存仍然足够,Quantity
不会改变。
2)如果根本没有库存,Quantity
为零。
3)在Quantity
部分减少之间可以有一行。
最后,使用Quantity
和Notes
的新值更新源表。
运行此查询CTE-by-CTE并检查中间结果以了解其工作原理。
示例数据
DECLARE @Items TABLE (LineID int PRIMARY KEY, ProductID int, Price money, Quantity int, Note nvarchar(4000));
INSERT INTO @Items (LineID, ProductID, Price, Quantity, Note) VALUES
(001, 00001, 100, 2, ''),
(002, 00001, 50, 2, ''),
(003, 00001, 0, 2, '');
DECLARE @Products TABLE (ProductID int PRIMARY KEY, BasePrice money, QuantityAvailable int);
INSERT INTO @Products (ProductID, BasePrice, QuantityAvailable) VALUES
(00001, 100, 3);
<强>查询强>
WITH
CTE
AS
(
SELECT
I.LineID
,I.ProductID
,I.Price
,I.Quantity
,I.Note
,P.QuantityAvailable
,SUM(I.Quantity) OVER (PARTITION BY I.ProductID ORDER BY I.LineID
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS SumQuantity
,SUM(I.Quantity) OVER (PARTITION BY I.ProductID ORDER BY I.LineID
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
- P.QuantityAvailable AS DiffQuantity
FROM
@Items AS I
INNER JOIN @Products AS P ON P.ProductID = I.ProductID
)
,CTE2
AS
(
SELECT
LineID
,ProductID
,Price
,Quantity
,Note
,QuantityAvailable
,DiffQuantity
,CASE WHEN DiffQuantity > 0 THEN 'Not enough stock' ELSE '' END AS NewNote
,CASE WHEN DiffQuantity > 0
THEN
CASE WHEN Quantity > DiffQuantity
THEN DiffQuantity
ELSE 0 END
ELSE Quantity END AS NewQuantity
FROM CTE
)
UPDATE CTE2
SET
Quantity = NewQuantity
,Note = NewNote
;
<强>结果强>
SELECT * FROM @Items;
+--------+-----------+--------+----------+------------------+
| LineID | ProductID | Price | Quantity | Note |
+--------+-----------+--------+----------+------------------+
| 1 | 1 | 100.00 | 2 | |
| 2 | 1 | 50.00 | 1 | Not enough stock |
| 3 | 1 | 0.00 | 0 | Not enough stock |
+--------+-----------+--------+----------+------------------+
答案 1 :(得分:0)
看看下面的查询,它可能对你有所帮助
update item set note = case when precedingSum> t.QuantityAvailable then 'Not Enough Stock' Else '' End
from
(
select item.*,Product.QuantityAvailable,sum(Quantity) over(partition by item.ProductId order by item.LineId rows UNBounded Preceding)precedingSum
from Item inner join Product on item.ProductId=Product.ProductId
) t where t.LineId = Item.LineId