Simulate lag function in MySQL












26














| 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









share|improve this question
























  • Are there only two per company? or is it variable?
    – Michael Berkowski
    Jul 3 '12 at 1:58












  • these are two companies
    – javanx
    Jul 3 '12 at 2:00










  • I see you have two companies here, but are there only ever two rows per company? If so you can use MAX() - MIN() aggregates trivially. If there are more than 2 rows per company, it is more complicated.
    – Michael Berkowski
    Jul 3 '12 at 2:01










  • I just need the latest two timestamp.. may be there are lot of entries for the same company but i just need to take the latest two time stamp and print the diff of quotes
    – javanx
    Jul 3 '12 at 2:02






  • 1




    In your example, why isn't the result negative for one of the companies? Google goes from 40 up to 60 whereas SAP goes from 60 down to 20. sqlfiddle.com/#!2/b62e1/1/0 Or do you only want the absolute movement irrespective of direction (in which case take ABS(delta))?
    – eggyal
    Jul 3 '12 at 8:48


















26














| 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









share|improve this question
























  • Are there only two per company? or is it variable?
    – Michael Berkowski
    Jul 3 '12 at 1:58












  • these are two companies
    – javanx
    Jul 3 '12 at 2:00










  • I see you have two companies here, but are there only ever two rows per company? If so you can use MAX() - MIN() aggregates trivially. If there are more than 2 rows per company, it is more complicated.
    – Michael Berkowski
    Jul 3 '12 at 2:01










  • I just need the latest two timestamp.. may be there are lot of entries for the same company but i just need to take the latest two time stamp and print the diff of quotes
    – javanx
    Jul 3 '12 at 2:02






  • 1




    In your example, why isn't the result negative for one of the companies? Google goes from 40 up to 60 whereas SAP goes from 60 down to 20. sqlfiddle.com/#!2/b62e1/1/0 Or do you only want the absolute movement irrespective of direction (in which case take ABS(delta))?
    – eggyal
    Jul 3 '12 at 8:48
















26












26








26


13





| 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









share|improve this question















| 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






mysql sql sliding-window






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 9 '14 at 10:16









Randell

4,58743969




4,58743969










asked Jul 3 '12 at 1:56









javanx

3881313




3881313












  • Are there only two per company? or is it variable?
    – Michael Berkowski
    Jul 3 '12 at 1:58












  • these are two companies
    – javanx
    Jul 3 '12 at 2:00










  • I see you have two companies here, but are there only ever two rows per company? If so you can use MAX() - MIN() aggregates trivially. If there are more than 2 rows per company, it is more complicated.
    – Michael Berkowski
    Jul 3 '12 at 2:01










  • I just need the latest two timestamp.. may be there are lot of entries for the same company but i just need to take the latest two time stamp and print the diff of quotes
    – javanx
    Jul 3 '12 at 2:02






  • 1




    In your example, why isn't the result negative for one of the companies? Google goes from 40 up to 60 whereas SAP goes from 60 down to 20. sqlfiddle.com/#!2/b62e1/1/0 Or do you only want the absolute movement irrespective of direction (in which case take ABS(delta))?
    – eggyal
    Jul 3 '12 at 8:48




















  • Are there only two per company? or is it variable?
    – Michael Berkowski
    Jul 3 '12 at 1:58












  • these are two companies
    – javanx
    Jul 3 '12 at 2:00










  • I see you have two companies here, but are there only ever two rows per company? If so you can use MAX() - MIN() aggregates trivially. If there are more than 2 rows per company, it is more complicated.
    – Michael Berkowski
    Jul 3 '12 at 2:01










  • I just need the latest two timestamp.. may be there are lot of entries for the same company but i just need to take the latest two time stamp and print the diff of quotes
    – javanx
    Jul 3 '12 at 2:02






  • 1




    In your example, why isn't the result negative for one of the companies? Google goes from 40 up to 60 whereas SAP goes from 60 down to 20. sqlfiddle.com/#!2/b62e1/1/0 Or do you only want the absolute movement irrespective of direction (in which case take ABS(delta))?
    – eggyal
    Jul 3 '12 at 8:48


















Are there only two per company? or is it variable?
– Michael Berkowski
Jul 3 '12 at 1:58






Are there only two per company? or is it variable?
– Michael Berkowski
Jul 3 '12 at 1:58














these are two companies
– javanx
Jul 3 '12 at 2:00




these are two companies
– javanx
Jul 3 '12 at 2:00












I see you have two companies here, but are there only ever two rows per company? If so you can use MAX() - MIN() aggregates trivially. If there are more than 2 rows per company, it is more complicated.
– Michael Berkowski
Jul 3 '12 at 2:01




I see you have two companies here, but are there only ever two rows per company? If so you can use MAX() - MIN() aggregates trivially. If there are more than 2 rows per company, it is more complicated.
– Michael Berkowski
Jul 3 '12 at 2:01












I just need the latest two timestamp.. may be there are lot of entries for the same company but i just need to take the latest two time stamp and print the diff of quotes
– javanx
Jul 3 '12 at 2:02




I just need the latest two timestamp.. may be there are lot of entries for the same company but i just need to take the latest two time stamp and print the diff of quotes
– javanx
Jul 3 '12 at 2:02




1




1




In your example, why isn't the result negative for one of the companies? Google goes from 40 up to 60 whereas SAP goes from 60 down to 20. sqlfiddle.com/#!2/b62e1/1/0 Or do you only want the absolute movement irrespective of direction (in which case take ABS(delta))?
– eggyal
Jul 3 '12 at 8:48






In your example, why isn't the result negative for one of the companies? Google goes from 40 up to 60 whereas SAP goes from 60 down to 20. sqlfiddle.com/#!2/b62e1/1/0 Or do you only want the absolute movement irrespective of direction (in which case take ABS(delta))?
– eggyal
Jul 3 '12 at 8:48














3 Answers
3






active

oldest

votes


















39














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:





  1. order by clause is important here just like it is in a regular
    window function.

  2. You might also want to use lag for company just to be sure that you are computing difference in quotes of the same company.

  3. You can also implement row counters in the same way @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.






share|improve this answer























  • I am getting error. DDL and DML statements are not allowed in the query panel for MySQL; only SELECT statements are allowed. Put DDL and DML in the schema panel.
    – javanx
    Jul 3 '12 at 17:51












  • Though the error does not indicate this, try enabling "allowMultiQueries". This is a connector paramenter. For JDBC connector, see: dev.mysql.com/doc/refman/5.1/en/… . Are you able to run it successfully from MySQL client?
    – Dojo
    Jul 3 '12 at 17:59










  • You can also try executing the two statements individually but in the same session.
    – Dojo
    Jul 3 '12 at 18:02






  • 10




    @javanx Hi, I'm the author of SQL Fiddle. The error message you mention was actually a bug in the way I was handling certain types of MySQL queries. Thanks to your message here, I recognized it as such and have worked out a solution that fixes it (see here, for example: sqlfiddle.com/#!2/4f8a1/2). Thanks!
    – Jake Feasel
    Jul 4 '12 at 5:03










  • Great!! Thanks a lot
    – javanx
    Jul 4 '12 at 17:00



















3














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






share|improve this answer































    2














    To achieve the desired result, first you need to find the last and next to last timestamps for each company. It is quite simple with the following query:



    SELECT c.company, c.mts, max(l.ts) AS lts
    FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
    LEFT JOIN cq l
    ON c.company = l.company AND c.mts > l.ts
    GROUP BY c.company, c.mts;


    Now you have to join this subquery with the original table to get the desired results:



    SELECT c.company, l.quote, coalesce(l1.quote, 0),
    (l.quote - coalesce(l1.quote, 0)) AS result
    FROM (SELECT c.company, c.mts, max(l.ts) AS lts
    FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
    LEFT JOIN cq l
    ON c.company = l.company AND c.mts > l.ts
    GROUP BY c.company, c.mts) AS c
    LEFT JOIN cq AS l ON l.company = c.company AND l.ts = c.mts
    LEFT JOIN cq AS l1 ON l1.company = c.company AND l1.ts = c.lts;


    You can observe results on SQL Fiddle.



    This query is using only standard SQL capabilities and should work on any RDBMS.






    share|improve this answer





















      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f11303532%2fsimulate-lag-function-in-mysql%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      39














      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:





      1. order by clause is important here just like it is in a regular
        window function.

      2. You might also want to use lag for company just to be sure that you are computing difference in quotes of the same company.

      3. You can also implement row counters in the same way @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.






      share|improve this answer























      • I am getting error. DDL and DML statements are not allowed in the query panel for MySQL; only SELECT statements are allowed. Put DDL and DML in the schema panel.
        – javanx
        Jul 3 '12 at 17:51












      • Though the error does not indicate this, try enabling "allowMultiQueries". This is a connector paramenter. For JDBC connector, see: dev.mysql.com/doc/refman/5.1/en/… . Are you able to run it successfully from MySQL client?
        – Dojo
        Jul 3 '12 at 17:59










      • You can also try executing the two statements individually but in the same session.
        – Dojo
        Jul 3 '12 at 18:02






      • 10




        @javanx Hi, I'm the author of SQL Fiddle. The error message you mention was actually a bug in the way I was handling certain types of MySQL queries. Thanks to your message here, I recognized it as such and have worked out a solution that fixes it (see here, for example: sqlfiddle.com/#!2/4f8a1/2). Thanks!
        – Jake Feasel
        Jul 4 '12 at 5:03










      • Great!! Thanks a lot
        – javanx
        Jul 4 '12 at 17:00
















      39














      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:





      1. order by clause is important here just like it is in a regular
        window function.

      2. You might also want to use lag for company just to be sure that you are computing difference in quotes of the same company.

      3. You can also implement row counters in the same way @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.






      share|improve this answer























      • I am getting error. DDL and DML statements are not allowed in the query panel for MySQL; only SELECT statements are allowed. Put DDL and DML in the schema panel.
        – javanx
        Jul 3 '12 at 17:51












      • Though the error does not indicate this, try enabling "allowMultiQueries". This is a connector paramenter. For JDBC connector, see: dev.mysql.com/doc/refman/5.1/en/… . Are you able to run it successfully from MySQL client?
        – Dojo
        Jul 3 '12 at 17:59










      • You can also try executing the two statements individually but in the same session.
        – Dojo
        Jul 3 '12 at 18:02






      • 10




        @javanx Hi, I'm the author of SQL Fiddle. The error message you mention was actually a bug in the way I was handling certain types of MySQL queries. Thanks to your message here, I recognized it as such and have worked out a solution that fixes it (see here, for example: sqlfiddle.com/#!2/4f8a1/2). Thanks!
        – Jake Feasel
        Jul 4 '12 at 5:03










      • Great!! Thanks a lot
        – javanx
        Jul 4 '12 at 17:00














      39












      39








      39






      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:





      1. order by clause is important here just like it is in a regular
        window function.

      2. You might also want to use lag for company just to be sure that you are computing difference in quotes of the same company.

      3. You can also implement row counters in the same way @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.






      share|improve this answer














      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:





      1. order by clause is important here just like it is in a regular
        window function.

      2. You might also want to use lag for company just to be sure that you are computing difference in quotes of the same company.

      3. You can also implement row counters in the same way @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.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jul 3 '12 at 19:13

























      answered Jul 3 '12 at 17:46









      Dojo

      3,12942654




      3,12942654












      • I am getting error. DDL and DML statements are not allowed in the query panel for MySQL; only SELECT statements are allowed. Put DDL and DML in the schema panel.
        – javanx
        Jul 3 '12 at 17:51












      • Though the error does not indicate this, try enabling "allowMultiQueries". This is a connector paramenter. For JDBC connector, see: dev.mysql.com/doc/refman/5.1/en/… . Are you able to run it successfully from MySQL client?
        – Dojo
        Jul 3 '12 at 17:59










      • You can also try executing the two statements individually but in the same session.
        – Dojo
        Jul 3 '12 at 18:02






      • 10




        @javanx Hi, I'm the author of SQL Fiddle. The error message you mention was actually a bug in the way I was handling certain types of MySQL queries. Thanks to your message here, I recognized it as such and have worked out a solution that fixes it (see here, for example: sqlfiddle.com/#!2/4f8a1/2). Thanks!
        – Jake Feasel
        Jul 4 '12 at 5:03










      • Great!! Thanks a lot
        – javanx
        Jul 4 '12 at 17:00


















      • I am getting error. DDL and DML statements are not allowed in the query panel for MySQL; only SELECT statements are allowed. Put DDL and DML in the schema panel.
        – javanx
        Jul 3 '12 at 17:51












      • Though the error does not indicate this, try enabling "allowMultiQueries". This is a connector paramenter. For JDBC connector, see: dev.mysql.com/doc/refman/5.1/en/… . Are you able to run it successfully from MySQL client?
        – Dojo
        Jul 3 '12 at 17:59










      • You can also try executing the two statements individually but in the same session.
        – Dojo
        Jul 3 '12 at 18:02






      • 10




        @javanx Hi, I'm the author of SQL Fiddle. The error message you mention was actually a bug in the way I was handling certain types of MySQL queries. Thanks to your message here, I recognized it as such and have worked out a solution that fixes it (see here, for example: sqlfiddle.com/#!2/4f8a1/2). Thanks!
        – Jake Feasel
        Jul 4 '12 at 5:03










      • Great!! Thanks a lot
        – javanx
        Jul 4 '12 at 17:00
















      I am getting error. DDL and DML statements are not allowed in the query panel for MySQL; only SELECT statements are allowed. Put DDL and DML in the schema panel.
      – javanx
      Jul 3 '12 at 17:51






      I am getting error. DDL and DML statements are not allowed in the query panel for MySQL; only SELECT statements are allowed. Put DDL and DML in the schema panel.
      – javanx
      Jul 3 '12 at 17:51














      Though the error does not indicate this, try enabling "allowMultiQueries". This is a connector paramenter. For JDBC connector, see: dev.mysql.com/doc/refman/5.1/en/… . Are you able to run it successfully from MySQL client?
      – Dojo
      Jul 3 '12 at 17:59




      Though the error does not indicate this, try enabling "allowMultiQueries". This is a connector paramenter. For JDBC connector, see: dev.mysql.com/doc/refman/5.1/en/… . Are you able to run it successfully from MySQL client?
      – Dojo
      Jul 3 '12 at 17:59












      You can also try executing the two statements individually but in the same session.
      – Dojo
      Jul 3 '12 at 18:02




      You can also try executing the two statements individually but in the same session.
      – Dojo
      Jul 3 '12 at 18:02




      10




      10




      @javanx Hi, I'm the author of SQL Fiddle. The error message you mention was actually a bug in the way I was handling certain types of MySQL queries. Thanks to your message here, I recognized it as such and have worked out a solution that fixes it (see here, for example: sqlfiddle.com/#!2/4f8a1/2). Thanks!
      – Jake Feasel
      Jul 4 '12 at 5:03




      @javanx Hi, I'm the author of SQL Fiddle. The error message you mention was actually a bug in the way I was handling certain types of MySQL queries. Thanks to your message here, I recognized it as such and have worked out a solution that fixes it (see here, for example: sqlfiddle.com/#!2/4f8a1/2). Thanks!
      – Jake Feasel
      Jul 4 '12 at 5:03












      Great!! Thanks a lot
      – javanx
      Jul 4 '12 at 17:00




      Great!! Thanks a lot
      – javanx
      Jul 4 '12 at 17:00













      3














      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






      share|improve this answer




























        3














        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






        share|improve this answer


























          3












          3








          3






          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






          share|improve this answer














          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







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited May 3 at 7:04

























          answered Apr 6 at 19:37









          Lukasz Szozda

          78.4k1061104




          78.4k1061104























              2














              To achieve the desired result, first you need to find the last and next to last timestamps for each company. It is quite simple with the following query:



              SELECT c.company, c.mts, max(l.ts) AS lts
              FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
              LEFT JOIN cq l
              ON c.company = l.company AND c.mts > l.ts
              GROUP BY c.company, c.mts;


              Now you have to join this subquery with the original table to get the desired results:



              SELECT c.company, l.quote, coalesce(l1.quote, 0),
              (l.quote - coalesce(l1.quote, 0)) AS result
              FROM (SELECT c.company, c.mts, max(l.ts) AS lts
              FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
              LEFT JOIN cq l
              ON c.company = l.company AND c.mts > l.ts
              GROUP BY c.company, c.mts) AS c
              LEFT JOIN cq AS l ON l.company = c.company AND l.ts = c.mts
              LEFT JOIN cq AS l1 ON l1.company = c.company AND l1.ts = c.lts;


              You can observe results on SQL Fiddle.



              This query is using only standard SQL capabilities and should work on any RDBMS.






              share|improve this answer


























                2














                To achieve the desired result, first you need to find the last and next to last timestamps for each company. It is quite simple with the following query:



                SELECT c.company, c.mts, max(l.ts) AS lts
                FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
                LEFT JOIN cq l
                ON c.company = l.company AND c.mts > l.ts
                GROUP BY c.company, c.mts;


                Now you have to join this subquery with the original table to get the desired results:



                SELECT c.company, l.quote, coalesce(l1.quote, 0),
                (l.quote - coalesce(l1.quote, 0)) AS result
                FROM (SELECT c.company, c.mts, max(l.ts) AS lts
                FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
                LEFT JOIN cq l
                ON c.company = l.company AND c.mts > l.ts
                GROUP BY c.company, c.mts) AS c
                LEFT JOIN cq AS l ON l.company = c.company AND l.ts = c.mts
                LEFT JOIN cq AS l1 ON l1.company = c.company AND l1.ts = c.lts;


                You can observe results on SQL Fiddle.



                This query is using only standard SQL capabilities and should work on any RDBMS.






                share|improve this answer
























                  2












                  2








                  2






                  To achieve the desired result, first you need to find the last and next to last timestamps for each company. It is quite simple with the following query:



                  SELECT c.company, c.mts, max(l.ts) AS lts
                  FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
                  LEFT JOIN cq l
                  ON c.company = l.company AND c.mts > l.ts
                  GROUP BY c.company, c.mts;


                  Now you have to join this subquery with the original table to get the desired results:



                  SELECT c.company, l.quote, coalesce(l1.quote, 0),
                  (l.quote - coalesce(l1.quote, 0)) AS result
                  FROM (SELECT c.company, c.mts, max(l.ts) AS lts
                  FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
                  LEFT JOIN cq l
                  ON c.company = l.company AND c.mts > l.ts
                  GROUP BY c.company, c.mts) AS c
                  LEFT JOIN cq AS l ON l.company = c.company AND l.ts = c.mts
                  LEFT JOIN cq AS l1 ON l1.company = c.company AND l1.ts = c.lts;


                  You can observe results on SQL Fiddle.



                  This query is using only standard SQL capabilities and should work on any RDBMS.






                  share|improve this answer












                  To achieve the desired result, first you need to find the last and next to last timestamps for each company. It is quite simple with the following query:



                  SELECT c.company, c.mts, max(l.ts) AS lts
                  FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
                  LEFT JOIN cq l
                  ON c.company = l.company AND c.mts > l.ts
                  GROUP BY c.company, c.mts;


                  Now you have to join this subquery with the original table to get the desired results:



                  SELECT c.company, l.quote, coalesce(l1.quote, 0),
                  (l.quote - coalesce(l1.quote, 0)) AS result
                  FROM (SELECT c.company, c.mts, max(l.ts) AS lts
                  FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
                  LEFT JOIN cq l
                  ON c.company = l.company AND c.mts > l.ts
                  GROUP BY c.company, c.mts) AS c
                  LEFT JOIN cq AS l ON l.company = c.company AND l.ts = c.mts
                  LEFT JOIN cq AS l1 ON l1.company = c.company AND l1.ts = c.lts;


                  You can observe results on SQL Fiddle.



                  This query is using only standard SQL capabilities and should work on any RDBMS.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jul 3 '12 at 18:22









                  vyegorov

                  14.3k63562




                  14.3k63562






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f11303532%2fsimulate-lag-function-in-mysql%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Florida Star v. B. J. F.

                      Danny Elfman

                      Lugert, Oklahoma