Select running total until specific SUM is reached

坚强是说给别人听的谎言 提交于 2019-11-30 15:31:46

Windowing Functions - SQL Server 2012 only

DECLARE @point INT = 200000;

;WITH x(rowid, ic, r, s) AS
(
  SELECT
    rowid, itemcount, ROW_NUMBER() OVER (ORDER BY itemage, rowid),
    SUM(itemcount) OVER (ORDER BY [itemage], rowid RANGE UNBOUNDED PRECEDING)
  FROM @agestuff
)
SELECT x.rowid, x.ic, x.s
FROM x WHERE x.s <= @point
ORDER BY x.rowid; 

Results:

rowid  ic      sum   
-----  ------  ------
1      175000  175000
2      300     175300
3      10000   185300

SQL fiddle demo

If you can't use SQL Server 2012 for some reason, then on SQL Server 2008 you can use a couple of alternatives:


Quirky Update

Note that this behavior is not documented, nor is it guaranteed to calculate your running totals in the correct order. So please use at your own risk.

DECLARE @st TABLE
(
    rowid INT PRIMARY KEY,
    itemcount INT,
    s INT
);

DECLARE @RunningTotal INT = 0;

INSERT @st(rowid, itemcount, s)
  SELECT rowid, itemcount, 0
    FROM @agestuff
    ORDER BY rowid;

UPDATE @st
  SET @RunningTotal = s = @RunningTotal + itemcount
  FROM @st;

SELECT rowid, itemcount, s
  FROM @st
  WHERE s < @point
  ORDER BY rowid;

Cursor

DECLARE @st TABLE
(
  rowid INT PRIMARY KEY, itemcount INT, s INT
);

DECLARE
  @rowid INT, @itemcount INT, @RunningTotal INT = 0;

DECLARE c CURSOR LOCAL FAST_FORWARD
  FOR SELECT rowid, itemcount
    FROM @agestuff ORDER BY rowid;

OPEN c;

FETCH c INTO @rowid, @itemcount;

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @RunningTotal = @RunningTotal + @itemcount;

    IF @RunningTotal > @point
      BREAK;

    INSERT @st(rowid, itemcount, s)
      SELECT @rowid, @itemcount, @RunningTotal;

    FETCH c INTO @rowid, @itemcount;
END

CLOSE c;
DEALLOCATE c;

SELECT rowid, itemcount, s
  FROM @st
  ORDER BY rowid;

I chose only two alternatives because others are even less desirable (mostly from a performance perspective). You can see them in the following blog post, with some background on how they perform and more information about potential gotchas. Don't paint yourself into a corner because you're stuck on the idea that cursors are bad - sometimes, like in this case, they can be the most efficient supported and reliable option:

http://www.sqlperformance.com/2012/07/t-sql-queries/running-totals

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!