如何在 MySQL 5.7 分组和排序中获取上一行值
How can I get previous row value in MySQL 5.7 grouping and ordering by
我有一个类似这样的数据集:
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
这已经是一个查询(因此,最终查询中的一个子查询),它通过时间戳对所有进度进行分组。我只是按 DATE
(以及 student_id
和 course_id
)分组并得到 MAX(progress)
以便将粒度设置为
STUDENT - COURSE - DATE
.
我需要检索每门课程的每个学生每天的进度。
那么,在那种情况下:
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
....
.....
.....
.....
.....
progress of day
是当天取得的进度减去前一天取得的进度
我设法使用带有条件的简单 JOIN 使它工作:
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
所以我可以从 t1
中得到 MAX(progress)
,从 t2
中得到 MAX(progress)
,然后简单地减去它们
但这表现不佳。实际上,我不能使用它,timeline
table 很大,我们唯一的索引是 student_id
,所以比较每一行之间的日期是疯狂的。我设法与几个学生和 LIMIT 一起完成了这项工作。
预期结果:与此相同,但表现良好。
我知道也许可以使用@variables,但我不知道如何进行。
想法?
谢谢
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
我有一个类似这样的数据集:
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 |
这已经是一个查询(因此,最终查询中的一个子查询),它通过时间戳对所有进度进行分组。我只是按 DATE
(以及 student_id
和 course_id
)分组并得到 MAX(progress)
以便将粒度设置为
STUDENT - COURSE - DATE
.
我需要检索每门课程的每个学生每天的进度。
那么,在那种情况下:
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 |
.... | ..... | ..... | ..... | ..... |
progress of day
是当天取得的进度减去前一天取得的进度
我设法使用带有条件的简单 JOIN 使它工作:
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
所以我可以从 t1
中得到 MAX(progress)
,从 t2
中得到 MAX(progress)
,然后简单地减去它们
但这表现不佳。实际上,我不能使用它,timeline
table 很大,我们唯一的索引是 student_id
,所以比较每一行之间的日期是疯狂的。我设法与几个学生和 LIMIT 一起完成了这项工作。
预期结果:与此相同,但表现良好。
我知道也许可以使用@variables,但我不知道如何进行。
想法?
谢谢
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