accumulated sum in query

喜夏-厌秋 提交于 2019-12-04 14:18:38

The following query:

SELECT * FROM 
(SELECT id, 
       count, 
       @running_count := @running_count + count AS Counter 
  FROM sumtest, (SELECT @running_count := 0) AS T1 ORDER BY id) AS TableCount 

WHERE TableCount.Counter < 50;

produces the results:

id  count   Counter
1   30      30
2   10      40
3   5       45

I copied your table into MySql and called it "sumtest" btw. Please replace with your table name.

Effectively, we work out the running total, in id order, then use that as a subquery.

So this query:

SELECT id, 
       count, 
       @running_count := @running_count + count AS Counter 
FROM sumtest, (SELECT @running_count := 0) AS T1 
ORDER BY id

Produces:

id  count   Counter
1   30      30
2   10      40
3   5       45
4   20      65
5   15      80

So then it becomes a trivial matter to select all those rows where the counter is less than your desired sum by performing another select on this.

EDIT: Here is an example with a cursor. I've just thrown this function together for you (note my table is called sumtest and my account is the default root@localhost):

DELIMITER $$

DROP FUNCTION IF EXISTS `Test_Cursing` $$
CREATE DEFINER=`root`@`localhost` FUNCTION `Test_Cursing`(_running_total_limit INT) RETURNS int
BEGIN
  /* Why am I on StackOverflow at 01:41 on New Years Day. Dear oh dear, where's the beer? */
  DECLARE _running_count INT default 0;
  DECLARE _id INT;
  DECLARE _current_id INT;
  DECLARE _sum_count INT;

  DECLARE _cur CURSOR FOR SELECT id, count FROM sumtest ORDER BY id;

  OPEN _cur;

  read_loop: LOOP
    FETCH _cur INTO _id, _sum_count;

    SET _running_count = _running_count + _sum_count;

    IF _running_count > _running_total_limit   THEN
      LEAVE read_loop;
    END IF;

    SET _current_id = _id;

  END LOOP;

  CLOSE _cur;

    RETURN _current_id;

END $$

DELIMITER ;

Calling it this way:

SELECT Test_Cursing(50);

will return id = 3 - that is, the last id before the running total limit is breached. You can then use this to:

 SELECT * FROM sumtest WHERE id <= Test_Cursing(50);

Which returns:

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