运行总计跳过某些值

时间:2019-06-20 16:52:53

标签: sql-server

我需要计算一个具有从“总计”列中减去“值”列的列,但是可以跳过行,直到不再找到较小的值为止。该顺序与日期有关,因此必须保留顺序。值(Need)不能大于总数,因为它们是事先删除的。

这是针对SQL Server 2016的。我最初的想法是使用窗口函数和运行总计,但是我无法弄清楚如何跳过400并继续到下面的2行。我在CASE语句中将我的尝试记为TransferQty,在运行总数中记作了ReferenceCol。

要复制的代码:

DECLARE @i TABLE
(
    sequence INT IDENTITY(1,1)
    ,Total INT
    ,Need INT
)
INSERT INTO @i 
VALUES (500,100)
,(500,200)
,(500,50)
,(500,400)
,(500,50)
,(500,50)

SELECT 
     sequence
    ,Total
    ,Need
    ,CASE 
        WHEN Total - SUM(Need) OVER (ORDER BY sequence) > 0 
        THEN Need 
    ELSE 0 
    END AS TransferQty
    ,Total - SUM(Need) OVER (ORDER BY sequence) as ReferenceCol
FROM @i

当前结果

+----------+-------+------+-------------+--------------+
| Sequence | Total | Need | TransferQty | ReferenceCol |
+----------+-------+------+-------------+--------------+
|        1 |   500 |  100 |         100 |          400 |
|        2 |   500 |  200 |         200 |          200 |
|        3 |   500 |   50 |          50 |          150 |
|        4 |   500 |  400 |           0 |         -250 |
|        5 |   500 |   50 |           0 |         -300 |
|        6 |   500 |   50 |           0 |         -350 |
+----------+-------+------+-------------+--------------+

所需结果

+----------+-------+------+-------------+--------------+
| Sequence | Total | Need | TransferQty | ReferenceCol |
+----------+-------+------+-------------+--------------+
|        1 |   500 |  100 |         100 |          400 |
|        2 |   500 |  200 |         200 |          200 |
|        3 |   500 |   50 |          50 |          150 |
|        4 |   500 |  400 |           0 |          150 | --skip calc
|        5 |   500 |   50 |          50 |          100 |
|        6 |   500 |   50 |          50 |           50 |
+----------+-------+------+-------------+--------------+

2 个答案:

答案 0 :(得分:0)

如果有一个跳过,则应该可以使用此代码,但是,如果有多个跳过,则必须循环遍历并基于滚动值超出总数的情况执行记录删除。

alert(event.target.dataset.value)

答案 1 :(得分:0)

这是我采用的解决方案,该解决方案基于原始评论中的“古怪更新”。

DROP TABLE IF EXISTS #i
GO

CREATE TABLE #i 
(
    sequence INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    ,Total INT
    ,Need INT
    ,RunningTransfer INT NULL
)

INSERT INTO #i 
VALUES 
 (500,100,NULL)
,(500,200,NULL)
,(500,50,NULL)
,(500,400,NULL)
,(500,50,NULL)
,(500,50,NULL)
,(500,100,NULL)
,(500,49,NULL)
,(500,50,NULL)

DECLARE @TransferRunningTotal INT

UPDATE #i
    SET @TransferRunningTotal = RunningTransfer = CASE 
                                                    --this skips values larger than running total
                                                    WHEN @TransferRunningTotal < Need THEN @TransferRunningTotal 
                                                    --this creates the running total
                                                    WHEN @TransferRunningTotal > Need THEN @TransferRunningTotal - Need 
                                                    --creates the initial value
                                                    ELSE Total - Need 
                                                 END
FROM #i WITH (TABLOCKX)
 OPTION (MAXDOP 1) 

SELECT sequence
      ,Total
      ,Need
      ,CASE 
            WHEN need <= RunningTransfer THEN Need
            ELSE 0 
      END AS TsfQty
      ,RunningTransfer 
FROM #i