Tutorial :Calculate a running total in MySQL



Question:

I have this MySQL query:

SELECT DAYOFYEAR(`date`)  AS d, COUNT(*)   FROM  `orders`   WHERE  `hasPaid` > 0  GROUP  BY d  ORDER  BY d  

Which returns something like this:

d  | COUNT(*) |  20 |  5       |  21 |  7       |  22 | 12       |  23 |  4       |  

What I'd really like is another column on the end to show the running total:

d  | COUNT(*) | ??? |  20 |  5       |   5 |  21 |  7       |  12 |  22 | 12       |  24 |  23 |  4       |  28 |  

Is this possible?


Solution:1

Perhaps a simpler solution for you and prevents the database having to do a ton of queries. This executes just one query then does a little math on the results in a single pass.

SET @runtot:=0;  SELECT     q1.d,     q1.c,     (@runtot := @runtot + q1.c) AS rt  FROM     (SELECT         DAYOFYEAR(`date`) AS d,         COUNT(*) AS c      FROM  `orders`      WHERE  `hasPaid` > 0      GROUP  BY d      ORDER  BY d) AS q1  

This will give you an additional RT (running total) column. Don't miss the SET statement at the top to initialize the running total variable first or you will just get a column of NULL values.


Solution:2

SELECT      DAYOFYEAR(O.`date`)  AS d,      COUNT(*),     (select count(*) from `orders`          where  DAYOFYEAR(`date`) <= d and   `hasPaid` > 0)  FROM      `orders` as O  WHERE      O.`hasPaid` > 0  GROUP  BY d  ORDER  BY d  

This will require some syntactical tuning (I don't have MySQL to test it), but it shows you the idea. THe subquery just has to go back and add up everything fresh that you already included in the outer query, and it has to do that for every row.

Take a look at this question for how to use joins to accomplish the same.

To address concerns about performance degradation with growing data: Since there are max. 366 days in a year, and I assume that you are not running this query against multiple years, the subquery will get evaluated up to 366 times. With proper indices on the date and the hasPaid flag, you'll be ok.


Solution:3

I would say that this is impossible every resulting row should be independent. Use programming language for getting these values


Solution:4

Unless you have no other option but doing this in sql, I'd sum the results in the programming language that is making the query. A nesting like this will became very slow as the table grows.


Solution:5

You can hack this using the Cross Join statement or some slef joins but it will get slow with any large data sets so probably best done in a post query processor; either cursor of in client code


Solution:6

This is one of the only places where cursors are faster than a set based queries, if performance is critical I would either

  • Do this outside of MySql or
  • Use MySql 5 Cursors

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »