Mysql how to sum column with previous column sum - mysql

In XLS I have two columns A and B.
A,B
1,1
2,3
2,5
1,6
5,11
2,13
A column have value, and B column is calculated with formula, (A + (previous row B value))
How can i do this calculation on MYSQL?
I'm trying to join same table twice and i can get previous rows A column next to B.
I can sum them, but how can I sum them with this formula?
XLS formula looks like this:
H20 = H19+G20
This is my SQL created from suggestions.
SELECT
date, time, sum, #b := sum+#b as 'AccSum', count
FROM
(SELECT
t.date, t.time, t.sum, t.count
FROM TMP_DATA_CALC t
ORDER BY t.epoch) as tb
CROSS JOIN
(SELECT #b := 0) AS var
;

SELECT A, #b := A+#b AS B
FROM (SELECT A
FROM YourTable
ORDER BY id) AS t
CROSS JOIN
(SELECT #b := 0) AS var
The user variable #b holds the value of B from the previous row, allowing you to add the current row's A to it.
DEMO

http://sqlfiddle.com/#!2/74488/2/1 shows how to select the data.
SET #runtot:=0;
Select a,b, #runtot:=#runtot+a from b
However there's an underlying problem I can't figure out. Since you don't have a defined order, the SQL could do this ordering in any way, so you may not get the desired results.. without a defined order you results may be unpredictable.
runtot = running total.

In MySQL we don't have any function like partition by which Oracle has. You can use curser to achieve your requirement. Or we can write any function which will get rownumber as input then add these two values then return that to query.
select b from xsl limit rownum-1,1 + select a from xsl limit rownum,1

Related

How to easily get row number when using LIMIT in MySQL?

Suppose I have a database table with quite a few rows which I want to display to an user. It would make sense to LIMIT the output, and make pages of rows. In MySQL I would do this:
SELECT * FROM myTable ORDER BY myValue LIMIT 120,10
which will show 10 rows starting from row 120. So MySQL must use, internally, some kind of order, and has numbered the rows accordingly. I would like to display the row number with each row. How do I get access to these numbers, using only MySQL? To be clear, I am looking for something like this:
SELECT *,<LIMIT_ROWNO> FROM myTable ORDER BY myValue LIMIT 120,10
I looked online and in the manual, but I cannot find it. I would prefer something simple, without using variables, or functions. Isn't there a predefined expression for this?
I can solve this problem easily in PHP, but it would be more logical to get the row numbers from MySQL.
You can't do it without using variables, e.g.:
SELECT m.*, #rownum := #rownum + 1 as `num`
FROM myTable m, (SELECT #rownum := 120) a
ORDER BY myValue LIMIT 120,10;
set #rownum=120;
SELECT *,#rownum:=#rownum+1 as rn FROM myTable ORDER BY myValue LIMIT 120,10;
as of final of 2021, why not:
SELECT
t1.*,
COUNT(t1.*) OVER (PARTITION BY RowCounter) as TotalRecords
FROM (
SELECT a, b, c, 1 as RowCounter
FROM MyTable
) t1
LIMIT 120,10
using a subquery with a column marking every row with the same value, will give us the possibility to count all of the same values of the the resulted column with PARTITION BY window function's group

Temporary Variable with aggregate field and group by doesn't work in mysql

I am trying to get cumulative value of a column using temporary variable.
SELECT sum(price), #temp := #temp + sum(price) AS cumulative_price FROM `table`, (SELECT #temp := 0) B GROUP BY item
It work when there is no group by and aggregate field. However, when there is group by field, value of cumulative_price is same as sum(price), which is not a expected.
What could be the reason of this inconsistency?
It should not work. According to Doc
In a SELECT statement, each select expression is evaluated only when
sent to the client. This means that in a HAVING, GROUP BY, or ORDER BY
clause, referring to a variable that is assigned a value in the select
expression list does not work as expected:
mysql> SELECT (#aa:=id) AS a, (#aa+3) AS b FROM tbl_name HAVING b=5;
The reference to b in the HAVING clause refers to an alias for an
expression in the select list that uses #aa. This does not work as
expected: #aa contains the value of id from the previous selected row,
not from the current row.
So when you define a variable it will work for current row not set of rows

MySQL same query result in multiple subqueries

I am trying to optimize following query.
SELECT t3.*,
(SELECT SUM(t4.col_sum)
FROM (...) t4
WHERE t4.timestamp BETWEEN CONCAT(SUBSTR(t3.timestamp, 1, 11), "00:00:00") AND t3.timestamp)
AS cum_sum
FROM (...) t3
Where (...) is a container for long query. It results 2 columns: timestamp and col_sum. I want to add third column to it by writing a query. That third column is a cumulative sum of col_sum.
The problem is I am putting same big query in two places (...)
Is there a way I can obtain a result and use the result in those two/multiple places (...)?
One method is to use a temporary table.
Probably a more efficient method is to use variables to calculate a cumulative sum. It would be something like:
select t.*,
(#c := if(#t = left(t.timestamp, 11), #c + t.col_sum,
if(#t := left(t.timestamp, 11), 0, 0)
)
) as cumesum
from (. . .) t cross join
(select #t := '', #c := 0) vars
order by t.timestamp;
The above query orders the rows by timestamp. The variable #t keeps track of the first 11 characters in the timestamp -- as I read your logic, you want to do the cumulative sum only within a group where this is constant.
The variable #c keeps track of the cumulative sum, resetting to zero when a new "first 11 characters" are encountered. The logic looks a bit complicated, but it is best to put all variable assignments in a single expression, because MySQL does not guarantee the order of evaluation of expressions.

mysql show position in resultset

So I have a list of say 10 rows. Each with an key and value.
Is there a way in mysql where I can, get a rows position in a given resultset:
SELECT 'resultSetPosition' FROM table WHERE rowKey=x ORDER BY rowValue
id value
1 a
2 b
3 c
o/p required
if id 3 the i need to get position of that row is 3
EDIT: I only want to get one row out in my resultset, but the 'position' should relate to its position for example if you sort by id.
(Obviously this whole thing is easy if I just pull the entire resultset and search the array in my programming, but I wanted to see if it could be done in mysql alone.)
You can try this:-
SELECT *, #rownum := #rownum + 1 AS ROW_NUMBER
FROM TABLE
JOIN (SELECT #rownum := 0) R;
This might help you.
Try this:
SET #rank=0;
SELECT #rank:=#rank+1 AS resultSetPosition
FROM tableName
WHERE rowKey=x
ORDER BY rowValue
Also take a look at this link.
Try with this hope this will clear your problem
select count(*) as pos from table_name where id<=current_id

In mysql, can I count how many rows satisfy some condition, if not then exit the count?

Basically I store data in MySql 5.5. I use qt to connect to mysql. I want to compare two columns, if col1 is greater than col2, the count continues, but when col1 is less than col2, count finishes and exits. So this is to count how many rows under some condition at the beginning of column. Is it possible in mysql?
An example:
Col1 Col2
2 1
2 3
2 1
The count I need should return 1, because the first row meets the condition of Col1 > Col2, but the second row doesn't. Whenever the condition is not meet, counting exits no matter if following rows meet the condition or not.
SELECT COUNT(*)
FROM table
WHERE col1 > col2
It's a little difficult to understand what you're after, but COUNT(*) will return the number of rows matched by your condition, if that's your desire. If it's not, can you maybe be more specific or show example(s) of what you're going for? I will do my best to correct my answer depending on additional details.
You should not be using SQL for this; any answer you get will be chock full of comprimise and if (for example) the result set from your intial query comes back in a different order (due to an index being created or changed), then they will fail.
SQL is designed for "set based" logic - and you really are after procedural logic. If you have to do this, then
1) Use a cursor
2) Use an order by statement
3) Cross fingers
This is a bit ugly, but will do the job. It'll need adjusting depending on any ORDER etc you would like to apply to someTable but the principle is sound.
SELECT COUNT(*)
FROM (
SELECT
#multiplier:=#multiplier*IF(t.`col1`<t.`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1
) scanQuery
The #multiplier variable will keep multiplying itself by 1. When it encounters a row where col1 < col2 it multiplies by 0. It will then continue multiplying 0 x 1. The outer query then just sums them up.
It's not ideal, but would suffice. This could be expanded to allow you to get those rows before the break by doing the following
SELECT
`someTable`.*
FROM `someTable`
INNER JOIN (
SELECT
`someTable`.`PrimaryKeyField`
#multiplier:=#multiplier*IF(`col1`<`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1
) t
ON scanQuery.`PrimaryKeyField` = `someTable`.`PrimaryKeyField`
Or possibly simply
SELECT
`someTable`.*
#multiplier:=#multiplier*IF(`col1`<`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1