I am using MySQL and need to display the sum of all the previous values, including the current row, for each row.
date | val | total
------------------
15M | 20 | 20
17M | 15 | 35
1APR | -5 | 30
-------------------
So, in the database I only have the date and the val for each date. I currently use SELECT date, val FROM table ORDER BY DATE ASC. How can I also add the total column? I guess I would use a SUM query, but how do I add the sum for every row?
In case you can use a variable, you can easily calculate cumulative sum
this way
set #csum := 0;
select date, val, (#csum := #csum + val) as cumulative_sum
from table
order by date DESC;
EDIT There is a way to define your variable in a join
select t.date, t.val, (#csum := #csum + t.val) as cumulative_sum
from table t
join (select #csum := 0) r
order by date DESC;
Related
I have an sql table trade with following data
id| value | price
1| 0.1 |1
2| 0.5 |2
3| 0.9 |2
4| 0.3 |2
How do I make an SQL query so that I get the count of entries limited to total value of 0.9 for price 2 ascending by id . For example:-
Select Count of id FROM trade WHERE sum(value) <= 0.9 and price = '2'
Result should come as
3
As there are total 3 entries with id 2,3,4 with values 0.5,0.9,0.3 with price 2 . The sum of them is 1.7 which is more than 0.9 but if we take 0.5 and 0.3 it combines to 0.8 which is lesser than 0.9 . So result should be 3 as it consists value of atleast 0.9 with price 2.
Also is there way to get the id of the results with last and first highest value in order.
So it looks like :-
4
2
3
Help appreciated :)
select id from
(select id, if(not(#sum > 0.9), 1, 0) mark, (#sum:=#sum+value) as sum
from trade cross join (select #sum:=0) s
where price=2 order by value asc) t
where mark =1
The inner query counts cumulative sum and addional field mark, which is equal one while sum is less and turn into zero when it is over 0.9. Since it's working one step later, it gathers the first row where sum is above the limit.
The result of the inner select
id mark sum
4 1 0.30000001192092896
2 1 0.800000011920929
3 1 1.699999988079071
Now in the outer query you just need to select rows with mark equal 1. And it results in 4,2,3
demo on sqlfiddle
You can achieve this by using a temporary SQL variable which stores partial sums and used rows count. Note that there are two SQL statements:
SET #tempsum := 0, #rowscount := 0;
SELECT MIN(tempcount) FROM
(SELECT
(#rowscount := #rowscount + 1) AS tempcount,
(#tempsum := #tempsum + value) AS tempsum
FROM trade WHERE
price='2'
ORDER BY value
) AS partialsums
WHERE tempsum>=0.9;
This way the partial sums are built only once. Without variables, you would need to build another subquery which builds multiple partial sums.
Here the SQL Fiddle: http://sqlfiddle.com/#!9/38fc2/11/1
See also: Create a Cumulative Sum Column in MySQL
You may also use variables to store the IDs involved, i.e.:
SET #tempsum := 0, #rowscount := 0, #ids := '';
SELECT MIN(tempcount), tempids FROM
(SELECT
(#tempsum := #tempsum + value) AS tempsum,
(#rowscount := #rowscount + 1) AS tempcount,
(#ids := concat(#ids, ' ', id)) AS tempids
FROM trade WHERE
price='2'
ORDER BY value
) AS partialsums
WHERE tempsum>=0.9;
See Fiddle: http://sqlfiddle.com/#!9/38fc2/33/0
If you need the count of the distinct ID values you could use count(distinct id)
and do the fact you checking for an aggregated result (sum() ..) you should use having and not where
Select Count(distinct id )
FROM trade
where price = 2
HAVING sum(value) <= 0.9
if you want the count for the rows with ID not null theb you could use count(id)
Select Count(id )
FROM trade
where price = 2
HAVING sum(value) <= 0.9
NB you are using price as a string
Is there a way to capture a cummulative sum with a reset condition in mySQL? The use case for this is a simple cash register table
id transactionType value CurrentBalance
1 purchase 10 10
2 sale -10 0
3 RESET 20 20
4 purchase 10 30
5 sale -10 20
6 sale 10 30
7 sale -20 10
The answer from here is a good starting point but I don't see how to extend it:
Create a Cumulative Sum Column in MySQL
SELECT t.id,
t.count,
#running_total := #running_total + t.value AS CurrentBalance
FROM TABLE t
JOIN (SELECT #running_total := 0) r
ORDER BY t.id
NOTE: basically the idea is to reset the cumulative sum each time a reset is hit. Ideally I am trying to have an on update/insert trigger which will update the entire CurrentBalance column taking into account RESETs. This is a small table so I don't mind updating the whole table in exchange for something simple.
All this requires is some simple conditional logic:
SELECT t.id, t.count,
#running_total := if(transactionType = 'RESET', t.value,
#running_total + t.value
) as CurrentBalance
FROM TABLE t JOIN
(SELECT #running_total := 0) params
ORDER BY t.id;
ID int(11) (NULL) NO PRI (NULL)
CREATED_DATE datetime (NULL) YES (NULL)
As mentioned above is some of field of my table 'User'.I want number of total user and cumulative count grouped on date.I used below query in mysql.
SELECT q1.CREATED_DATE,q1.NO_OF_USER, (#runtot := #runtot + q1.NO_OF_USER) AS CUMM_REGISTRATION FROM (SELECT date(CREATED_DATE) AS CREATED_DATE,
COUNT(ID) AS NO_OF_USER FROM USER,(SELECT #runtot:=0) AS n GROUP BY CREATED_DATE ORDER BY CREATED_DATE) AS q1
Which is working fine.Now I want one more additional data which will be 'CUMULATIVE USER COUNT SINCE 1 AUGUST '.Is it possible to fetch this modifying above query or its better to handle in code?Please suggest.
You can do this by adding another variable and doing it in the code:
SELECT q1.CREATED_DATE, q1.NO_OF_USER,
(#runtot := #runtot + q1.NO_OF_USER) AS CUMM_REGISTRATION,
#Aug1tot := if(CREATED_DATE >=date('2013-08-01'), #Aug1tot + q1.NO_OF_USER, NULL) as CUMM_SINCE_Aug1
FROM (SELECT date(CREATED_DATE) AS CREATED_DATE,
COUNT(ID) AS NO_OF_USER
FROM USER cross join
(SELECT #runtot:=0, #Aug1tot := 0) n
GROUP BY date(CREATED_DATE)
ORDER BY date(CREATED_DATE);
) AS q1
I guess you have some function called MONTH(yourDate) in mySQL, where MONTH(15-Aug-2013) will return 8.
You could either group your results per MONTH(yourDate), or filter your original data for MONTH(yourDate) = 8. Be careful if your data runs along multiple years, as all dates where month = 8 will be cumulated. You could then add a sorting / filtering critera based on YEAR(yourDate)
I have a MySQL table with 4 columns as follows.
TransactionID | Item | Amount | Date
------------------------------------
| | |
| | |
I have a lot of entries and what I want to be able to do is create a query that returns a list of the total Profit/Loss at each point in time?
Imagine I had the following transactions:
Bought item for 5
Sold item for 15
Bought item for 5
Sold item for 15
So I would want it to return something like this.
Profit/Loss | Date
------------------
-5 | 20-10-12
10 | 21-10-12
5 | 22-10-12
20 | 23-10-12
Is this possible with a MySQL query?
SELECT SUM(Amount) AS ProfitOrLoss FROM TableName GROUP BY Date
Assuming that Date is stored as you show on the expected result this should work:
SELECT
SUM(Amount) AS "Profit/Loss",
Date
FROM your_table
GROUP BY(Date)
Otherwise id Date is of type DATE, DATETIME or TIMESTAMP you could do something like this:
SELECT
SUM(Amount) AS "Profit/Loss",
DATE_FORMAT(Date, '%d-%m-%y') AS Date
FROM your_table
GROUP BY(DATE_FORMAT(Date, '%d-%m-%y'))
references:
DATE_FORMAT
GROUP BY
EDIT (after OP's comment)
to achieve the comulative SUM here is a good hint:
SET #csum := 0;
SELECT
(#csum := #csum + x.ProfitLoss) as ProfitLoss,
x.Date
FROM
(
SELECT
SUM(Amount) AS ProfitLoss,
DATE_FORMAT(Date, '%d-%m-%y') AS Date
FROM your_table
GROUP BY(DATE_FORMAT(Date, '%d-%m-%y'))
) x
order by x.Date;
essentialy you store the current sum into a variable (#csum) and for each row of the grouped transactions you increase it by the daily balance
SELECT SUM(Amount) FROM TableName GROUP BY Date
i want to make some daily report which order by date.
i want this data can increase every day.
Date qty QP
2010-09-01 10 10
2010-09-02 3 13 (it means result QP from 2010-09-01 accumulate with 2010-09-02)
2010-09-03 8 21
this is the 1st code:
SELECT Date, SUM(number) AS qty FROM calc GROUP BY Date
how do i do to show "QP" if for actually i dont need to show "qty" field(automatic count) just show Date and QP but it still can count?
SET #r := 0;
SELECT date, #sum := SUM(number) AS qty, #r := #r + #sum AS qp
FROM calc
GROUP BY
date
This example will help you for sure:
MySQL select "accumulated" column