【问题标题】:Insert only up to a maximum number?只插入最大数量?
【发布时间】:2017-08-16 01:18:21
【问题描述】:

我有一个现有的存储过程,它将购物车项目作为单独的行返回,其中一个字段是所述项目的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 中,该表通过 ProductID 连接到产品 products 表中,如下所示:

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:电动布加洛

我尝试使用局部变量来计算运行总值,但这似乎直接跳到总值。示例如下:

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       | 

【问题讨论】:

  • 如果您包含一些说明问题的示例数据,可能有助于其他人理解您的问题。

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


【解决方案1】:

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

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

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

最后,源表更新为 Quantity 和 Notes 的新值。

逐个 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 |
+--------+-----------+--------+----------+------------------+

【讨论】:

    【解决方案2】:

    看看下面的查询,它可能对你有帮助

        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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-24
      • 2021-12-24
      • 1970-01-01
      • 2019-11-22
      • 2023-04-10
      • 1970-01-01
      • 2015-10-16
      • 1970-01-01
      相关资源
      最近更新 更多