| time | company | quote | +---------------------+---------+-------+ | 0000-00-00 00:00:00 | GOOGLE | 40 | | 2012-07-02 21:28:05 | GOOGLE | 60 | | 2012-07-02 21:28:51 | SAP | 60 | | 2012-07-02 21:29:05 | SAP | 20 |
How do I do a lag on this table in MySQL to print the difference in quotes, for example:
GOOGLE | 20 SAP | 40
The LEAD() and LAG() function in MySQL are used to get preceding and succeeding value of any row within its partition. These functions are termed as nonaggregate Window functions. The Window functions are those functions which perform operations for each row of the partition or window.
LAG provides access to a row at a given physical offset that comes before the current row. Use this analytic function in a SELECT statement to compare values in the current row with values in a previous row.
The LEAD function is used to access data from SUBSEQUENT rows along with data from the current row. The LAG function is used to access data from PREVIOUS rows along with data from the current row.
This is my favorite MySQL hack.
This is how you emulate the lag function:
SET @quot=-1; select time,company,@quot lag_quote, @quot:=quote curr_quote from stocks order by company,time;
lag_quote
holds the value of previous row's quote. For the first row @quot is -1.curr_quote
holds the value of current row's quote.Notes:
order by
clause is important here just like it is in a regular window function. company
just to be sure that you are computing difference in quotes of the same company
.@cnt:=@cnt+1
The nice thing about this scheme is that is computationally very lean compared to some other approaches like using aggregate functions, stored procedures or processing data in application server.
EDIT:
Now coming to your question of getting result in the format you mentioned:
SET @quot=0,@latest=0,company=''; select B.* from ( select A.time,A.change,IF(@comp<>A.company,1,0) as LATEST,@comp:=A.company as company from ( select time,company,quote-@quot as change, @quot:=quote curr_quote from stocks order by company,time) A order by company,time desc) B where B.LATEST=1;
The nesting is not co-related so not as bad (computationally) as it looks (syntactically) :)
Let me know if you need any help with this.
From MySQL 8.0 and above there is no need to simulate LAG
. It is natively supported,
Window Function :
Returns the value of expr from the row that lags (precedes) the current row by N rows within its partition. If there is no such row, the return value is default. For example, if N is 3, the return value is default for the first two rows. If N or default are missing, the defaults are 1 and NULL, respectively.
SELECT company, quote, LAG(quote) OVER(PARTITION BY company ORDER BY time) AS prev_quote FROM tab;
DBFiddle Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With