Home > Back-end >  Extract difference in consecutive values for MySQL 5.7
Extract difference in consecutive values for MySQL 5.7

Time:07-18

Name Date Hours Count
Mills 2022-07-17 23 12
Mills 2022-07-18 00 15
Mills 2022-07-18 01 20
Mills 2022-07-18 02 22
Mills 2022-07-18 03 25
Mills 2022-07-18 04 20
Mills 2022-07-18 05 22
Mills 2022-07-18 06 25
MIKE 2022-07-18 00 15
MIKE 2022-07-18 01 20
MIKE 2022-07-18 02 22
MIKE 2022-07-18 03 25
MIKE 2022-07-18 04 20

My current input table stores information for counts recorded in each hour of the day consecutively. I need to extract the difference in values for consecutive counts but I'm having trouble doing it since I'm forced to use MySQL 5.7.

I have written the query as follows:

SET @cnt := 0;
SELECT Name, Date, Hours, Count, (@cnt := @cnt - Count) AS DiffCount
FROM Hourly
ORDER BY Date;

which is not giving exact results.

I expect to have the following output:

Name Date Hours Count Diff
Mills 2022-07-17 23 12 0
Mills 2022-07-18 00 15 3
Mills 2022-07-18 01 20 5
Mills 2022-07-18 02 22 2
Mills 2022-07-18 03 25 3
Mills 2022-07-18 04 20 5
Mills 2022-07-18 05 22 2
Mills 2022-07-18 06 25 3
MIKE 2022-07-18 00 15 0
MIKE 2022-07-18 01 20 5
MIKE 2022-07-18 02 22 2
MIKE 2022-07-18 03 25 3
MIKE 2022-07-18 04 20 5
MIKE 2022-07-18 05 22 2
MIKE 2022-07-18 06 25 3

Please suggest what I'm missing.

CodePudding user response:

Try the following:

SET @count=(select Count_ from Hourly order by Date_,Hours LIMIT 1);

select  Name,Date_,Hours,Count_,
ABS(curr_count-lag_count) as DiffCount
From
(
  select Name,Date_,Hours,Count_, 
  @count lag_count, @count:=Count_ curr_count
  From Hourly order by Date_,Hours
) D;

See a demo from db-fiddle.

CodePudding user response:

In MySQL 5.7 you can update your variable inline in order to contain your updated value of "Count". Since when the value of "Name" changes you need to reset your variable, you can use another variable that contains the previous "Name" value. Then you use an IF function to check:

  • if your previous name is equal to your current name
  • then take the difference in counts
  • else assign 0

It would be combined with the ABS function, which applies the absolute value on the difference.

SET @cnt  := NULL;
SET @name := NULL;

SELECT Date,
       Hours,
       ABS(IF(@name = Name, 
              @cnt := @cnt - Count,
              0)                    ) AS DiffCount,
       (@name := Name)                AS Name,
       (@cnt := Count)                AS Count
FROM tab
ORDER BY Name DESC,
         Date, 
         Hours;

Check the demo here.


In MySQL 8.0 you can use a window fuction like LAG to get your output smoothly. It would be combined with:

  • ABS that applies the absolute value on the difference,
  • COALESCE employed for removing the first null value.
SELECT *, 
       COALESCE(ABS(
           Count - LAG(Count) OVER(
                       PARTITION BY Name
                       ORDER     BY Date, Hours
                   )
       ), 0) AS Diff 
FROM tab
ORDER BY Name DESC, 
         Date, 
         Hours

Check the demo here.

  • Related