sql server-sql更新-按顺序提交每一行



早上好。我会尽我所能在不发布SQL的情况下解释我的问题(共650行)。如果需要更多信息,请告诉我。

我们有一个内部履行系统,实时分配库存。为了使分配正常工作,我们需要知道每次用户询问他们应该处理什么时有多少库存可用(通过加载/重新加载他们的任务列表)。数据看起来像这样:

ID    ItemID    QtyOrdered    QtyAvailableAfterAllocation    ParentID
1     1234      5             500                            NULL
2     1234      15            485                            1
3     1234      10            475                            2

当前正在使用while循环来设置QtyAvailableAfterAllocation列。上面的例子说明了循环的必要性。行2的QtyAvailableAfterAllocation取决于行1的QtyavailableAfter Allocation的值。第3行依赖于第2行,依此类推

这是逻辑的(非常)简化版本。当你考虑到套件(属于单亲项目的库存项目组)时,它会变得更加复杂。有时,库存不需要分配给物品,因为它存在于有足够库存来完成订单的试剂盒中。这就是为什么我们不能做一个连续的总数。此外,套件可以嵌套在第N级套件中。这就是问题所在。当处理大量具有嵌套套件的订单时,查询的性能非常差。我认为循环是罪魁祸首(测试已经证明了这一点)。所以,问题来了:

是否可以提交更新,一次一行,按特定顺序(无循环),以便下面的子记录可以访问父记录中的更新列(QtyAvailAfterOrder_AllocationScope)?

编辑

以下是SQL的一小部分。这是实际的while循环。也许这将有助于显示确定每个记录的分配所需的逻辑。

http://pastebin.com/VM9iasq9

你能作弊并做这样的事情吗?

DECLARE @CurrentCount int
SELECT @CurrentCount = QtyAvailableAfterAllocation 
FROM blah 
WHERE <select the parent of the first row>
UPDATE blah
SET QtyAvailableAfterAllocation = @CurrentCount - QtyOrdered,
    @CurrentCount = @CurrentCount - QtyOrdered
WHERE <it is valid to deduct the count>

这应该允许您保持基于设置的更新,并从起始数量开始向下计数。这里问题的关键是WHERE子句。

我们一直在做的一种方法是将值的层次结构(在您的案例中,是第N个工具包的想法)展平到一个表中,然后您可以连接到这个平面表上。层次结构的扁平化和单一连接应该有助于缓解一些性能上的怪癖。也许可以使用视图来压平数据。

很抱歉,这不是一个直接的答案,只是一些想法。

如果您能提供一个示例数据结构来显示试剂盒的适用性,我相信有人可以帮助研究出更具体的解决方案。

如果确实有请求以某种结构排队,则不会使用SQL语句来处理队列;"队列"one_answers"SQL"在概念上是不一致的:SQL是基于设置的,而不是过程性的。

因此,忘记使用查询来管理排队的请求,而是在一个过程中处理队列,将每个零件申请包装在一个事务中:

        pseudo:
        WHILE REQUESTS_REMAIN_IN_QUEUE
             begin trans
                execute requisition SQL statements
             commit
        LOOP

您的请购单(简化)可能如下所示:

           update inventory
           set QOH = QOH- {requested amount}
           where  partno = ? and QOH >= {requested amount}
           insert orderdetail
           (customer, orderheaderid, partno, requestedamount)
           values
           (custid, orderheaderid, partno, requested_amount)

现在,在一个涉及套件和自定义业务逻辑的复杂系统中,您可能有一条规则,如果套件中的每个组件都不可用,则不减少库存。然后,如果您遇到套件中的单个组件被延期订购的情况,您必须将您的套件申请包装在事务中并回滚。

我认为这个问题可以使用纯基于集合的方法来解决。

基本上,您需要执行以下步骤:

  1. 获取每个项目的当前可用数量表。

  2. 从要处理的订购数量中获取运行总数。

  3. 从每个项目的可用数量中减去其运行总数,得到每个项目的QtyAvailableAfterAllocation

这是一个示例解决方案:

/* sample data definition & initialisation */
DECLARE @LastQty TABLE (Item int, Qty int);
INSERT INTO @LastQty (Item, Qty) 
  SELECT 0123, 404 UNION ALL
  SELECT 1234, 505 UNION ALL
  SELECT 2345, 606 UNION ALL
  SELECT 3456, 707 UNION ALL
  SELECT 4567, 808 UNION ALL
  SELECT 5678, 909;
DECLARE @Orders TABLE (ID int, Item int, OrderedQty int);
INSERT INTO @Orders (ID, Item, OrderedQty)
  SELECT 1, 1234,  5 UNION ALL
  SELECT 2, 1234, 15 UNION ALL
  SELECT 3, 2345,  3 UNION ALL
  SELECT 4, 1234, 10 UNION ALL
  SELECT 5, 2345, 37 UNION ALL
  SELECT 6, 2345, 45 UNION ALL
  SELECT 7, 3456, 50 UNION ALL
  SELECT 8, 4567, 25 UNION ALL
  SELECT 9, 2345, 30;
/* the actuall query begins here */
WITH RankedOrders AS (
  SELECT
    *,
    rn = ROW_NUMBER() OVER (PARTITION BY Item ORDER BY ID)
  FROM @Orders
),
RunningOrderTotals AS (
  SELECT
    ID,
    Item,
    OrderedQty,
    RunningTotalQty = OrderedQty,
    rn
  FROM RankedOrders
  WHERE rn = 1
  UNION ALL
  SELECT
    o.ID,
    o.Item,
    o.OrderedQty,
    RunningTotalQty = r.RunningTotalQty + o.OrderedQty,
    o.rn
  FROM RankedOrders o
    INNER JOIN RunningOrderTotals r ON o.Item = r.Item AND o.rn = r.rn + 1
)
SELECT
  t.ID,
  t.Item,
  t.OrderedQty,
  QtyAvailableAfterAllocation = oh.Qty - t.RunningTotalQty
FROM RunningOrderTotals t
  INNER JOIN @LastQty oh ON t.Item = oh.Item
ORDER BY t.ID;

注意:在我的示例中,我手动初始化了可用项目数量表(@LastQty)。然而,你很可能会从你的数据中得到它。

基于上面的注释/答案,以及我无法正确准确地表示这个复杂的问题,我用C#重写了处理过程。使用PLINQ,我将处理时间从15秒减少到了4秒。感谢所有试图提供帮助的人!

如果这不是结束问题的合适方式,请告诉我(并让我知道合适的方式,这样我就可以这样做了)。

最新更新