仅插入最大数量?

时间:2017-08-16 01:18:22

标签: sql sql-server sql-server-2014

我有一个现有的存储过程,它将购物车项目作为单独的行返回,其中一个字段为所述项目的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       | 

2 个答案:

答案 0 :(得分:1)

在SQL Server 2014中计算运行总计很容易,只需使用SUM() OVER (...)即可。结果的排序对于运行总计很重要,我使用LineID来排序行。您可以选择其他适合您的订购。

下面查询中的第一个CTE计算每个产品的运行总计,差异DiffQuantity告诉我们产品耗尽的行。

Quantity的新值是三种可能性之一: 1)如果库存仍然足够,Quantity不会改变。 2)如果根本没有库存,Quantity为零。 3)在Quantity部分减少之间可以有一行。

最后,使用QuantityNotes的新值更新源表。

运行此查询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