Using user variables, you calculate running total for each line like a spreadsheet
PROPOSED QUERY
SET @total = 0;
SET @curr_trx = 0;
SET @curr_con = 0;
SET @lineitem = 0;
SELECT GrandTotal FROM
(
SELECT
(@lineitem:=@lineitem+1) line,
(@prev_con:=@curr_con),
(@curr_con:=connect_time),
(@prev_trx:=@curr_trx),
(@curr_trx:=transmitted),
(@newvalue:=IF(@prev_con>@curr_con,@prev_trx+@curr_trx,ABS(@prev_trx-@curr_trx))) newval,
(@total:=@total+@newvalue) GrandTotal
FROM mytable
) A WHERE line = @lineitem;
YOUR SAMPLE DATA
mysql> DROP DATABASE IF EXISTS timyash;
Query OK, 1 row affected (0.22 sec)
mysql> CREATE DATABASE timyash;
Query OK, 1 row affected (0.00 sec)
mysql> USE timyash
Database changed
mysql> CREATE TABLE mytable
-> (
-> id INT NOT NULL AUTO_INCREMENT,
-> transmitted INT NOT NULL,
-> connect_time INT NOT NULL,
-> PRIMARY KEY (id)
-> );
Query OK, 0 rows affected (0.35 sec)
mysql> INSERT INTO mytable (transmitted,connect_time) VALUES
-> (2650131,117987),(6465178,78073),(25905117,159268),
-> (59178089,410282),(73502942,596408),(75695427,683045),
-> (77576167,740379);
Query OK, 7 rows affected (0.03 sec)
Records: 7 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM mytable;
+----+-------------+--------------+
| id | transmitted | connect_time |
+----+-------------+--------------+
| 1 | 2650131 | 117987 |
| 2 | 6465178 | 78073 |
| 3 | 25905117 | 159268 |
| 4 | 59178089 | 410282 |
| 5 | 73502942 | 596408 |
| 6 | 75695427 | 683045 |
| 7 | 77576167 | 740379 |
+----+-------------+--------------+
7 rows in set (0.00 sec)
mysql>
PROPOSED QUERY EXECUTED
mysql> SET @total = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> SET @curr_trx = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> SET @curr_con = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> SET @lineitem = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT GrandTotal FROM
-> (
-> SELECT
-> (@lineitem:=@lineitem+1) line,
-> (@prev_con:=@curr_con),
-> (@curr_con:=connect_time),
-> (@prev_trx:=@curr_trx),
-> (@curr_trx:=transmitted),
-> (@newvalue:=IF(@prev_con>@curr_con,@prev_trx+@curr_trx,ABS(@prev_trx-@curr_trx))) newval,
-> (@total:=@total+@newvalue) GrandTotal
-> FROM mytable
-> ) A WHERE line = @lineitem;
+------------+
| GrandTotal |
+------------+
| 82876429 |
+------------+
1 row in set (0.08 sec)
mysql>
PROPOSED QUERY EXPLAINED
Look at the subquery
SELECT
(@lineitem:=@lineitem+1) line,
(@prev_con:=@curr_con),
(@curr_con:=connect_time),
(@prev_trx:=@curr_trx),
(@curr_trx:=transmitted),
(@newvalue:=IF(@prev_con>@curr_con,@prev_trx+@curr_trx,ABS(@prev_trx-@curr_trx))),
(@total:=@total+@newvalue) GrandTotal
FROM mytable
If you run this with the variables, you see everything being added up for you line by line
mysql> SET @total = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> SET @curr_trx = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> SET @curr_con = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> SET @lineitem = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT
-> (@lineitem:=@lineitem+1) line,
-> (@prev_con:=@curr_con),
-> (@curr_con:=connect_time),
-> (@prev_trx:=@curr_trx),
-> (@curr_trx:=transmitted),
-> (@newvalue:=IF(@prev_con>@curr_con,@prev_trx+@curr_trx,ABS(@prev_trx-@curr_trx))) newval,
-> (@total:=@total+@newvalue) GrandTotal
-> FROM mytable;
+------+------------------------+---------------------------+------------------------+--------------------------+----------+------------+
| line | (@prev_con:=@curr_con) | (@curr_con:=connect_time) | (@prev_trx:=@curr_trx) | (@curr_trx:=transmitted) | newval | GrandTotal |
+------+------------------------+---------------------------+------------------------+--------------------------+----------+------------+
| 1 | 0 | 117987 | 0 | 2650131 | 2650131 | 2650131 |
| 2 | 117987 | 78073 | 2650131 | 6465178 | 9115309 | 11765440 |
| 3 | 78073 | 159268 | 6465178 | 25905117 | 19439939 | 31205379 |
| 4 | 159268 | 410282 | 25905117 | 59178089 | 33272972 | 64478351 |
| 5 | 410282 | 596408 | 59178089 | 73502942 | 14324853 | 78803204 |
| 6 | 596408 | 683045 | 73502942 | 75695427 | 2192485 | 80995689 |
| 7 | 683045 | 740379 | 75695427 | 77576167 | 1880740 | 82876429 |
+------+------------------------+---------------------------+------------------------+--------------------------+----------+------------+
7 rows in set (0.00 sec)
mysql>
The proposed query has the subquery return a lineitem number. I get the last one to show the final total.
Remember the formula from your question ?
if connect_time[i] > connect_time[j]
then total += transmitted[i]+transmitted[j]
else total += ABS(transmitted[i]-transmitted[j])
end
The newval column computes the formula
Best Answer
You need to join the table to itself. One instance of the table to find the values of the "current" row and the second to look for the first row that the values differ.
Since the date parameter may not exist in the table, we also need a subquery (derived table, named
c
) to find the previous row that holds the values for the "current" date:Tested at SQLfiddle.
This part:
is just a compact way to write:
I assumed that the four time columns are not nullable. If they are nullable, the above expression would need to be more complicated.