How can I get previous row value in MySQL 5.7 grouping and ordering by
I have a dataset similar to this:
TABLE TIMELINE
student_id | course_id | date | progress |
---|---|---|---|
50 | 1 | 2022-01-01 | 0.1 |
50 | 1 | 2022-01-02 | 0.3 |
50 | 1 | 2022-01-03 | 0.7 |
50 | 3 | 2022-01-01 | 0.2 |
50 | 3 | 2022-01-02 | 0.3 |
50 | 3 | 2022-01-03 | 0.9 |
73 | 2 | 2022-01-01 | 0.1 |
73 | 2 | 2022-01-02 | 0.4 |
This is already a query (so, a subquery in the final query) that group all the progress through the timestamp. I just grouped by DATE
(and student_id
and course_id
) and got the MAX(progress)
in order to have the granularity set to
STUDENT - COURSE - DATE
.
I need to retrieve the progress for each day for each student for each course.
So, in that case:
student_id | course_id | date | progress | progress_of_day |
---|---|---|---|---|
50 | 1 | 2022-01-01 | 0.1 | 0.1 |
50 | 1 | 2022-01-02 | 0.3 | 0.2 |
50 | 1 | 2022-01-03 | 0.7 | 0.4 |
.... | ..... | ..... | ..... | ..... |
The progress of day
is the progress achieved that day minus progress achieved previous day
I managed to get this working using a simple JOIN with conditions:
timeline t1 LEFT JOIN timeline t2
ON t1.student_id = t2.student_id
AND t1.course_id = t2.course_id
AND t1.date > t2.date ## <---- THE SOLUTION BUT ALSO THE PROBLEM
So I could get MAX(progress)
out of t1
and MAX(progress)
out of t2
and simple subtract them
BUT this isn't performing well. Actually, I can't use it, the timeline
table is massive and the only indexes we have is on student_id
, so comparing the date between each row is insane. I managed to make this work with a few students and with LIMIT.
Expected result: the same I would achieve with this, but performing well.
I know maybe it is possible to do with @variables, but I don't know how to proceed.
Ideas?
Thanks
SELECT student_id,
course_id,
`date`,
CASE WHEN @group = CONCAT(student_id, '-', course_id)
THEN CAST(progress - @progress AS DECIMAL(2,1))
ELSE progress
END progress_of_day,
@group := CONCAT(student_id, '-', course_id),
@progress := progress progress
FROM timeline
CROSS JOIN ( SELECT @group := '', @progress := 0 ) variables
ORDER BY student_id, course_id, `date`
https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=650b940341e91b266fdd626bd4766566