I have two tables in my database that looks like this
learner_lessons
learnerlessonid learnerid lessonid 1 24 42
learner_lesson_logs
lessonlogid learnerlessonid progress maxprogress interaction createdAt 1 1 0 15 Start 2022-11-02 07:51:30 2 1 4 15 Pause 2022-11-02 07:51:34 3 1 4 15 Play 2022-11-02 07:52:20 4 1 14 15 Run 2022-11-02 07:52:30 5 1 15 15 Stop 2022-11-02 07:52:31
Basically, when a user clicks on a video it starts playing and the interaction is recorded as ‘Start’ and a timestamp is created accordingly. Now when a user pauses the video another interaction ‘Pause’ is created and the timestamp is recorded. The user might come back later and resume the video thus creating a ‘Play’ interaction. After every 10 seconds of the video if it isn’t paused another interaction ‘Run’ is logged in the database. Finally when the video ends ‘Stop’ interaction is created.
What I am aiming to achieve is the difference in timestamps when a video is ‘Started’ or ‘Played’ till the video is ‘Paused’ or ‘Stopped’. The interactions could be ‘Start’, and ‘Stop’ as well.
This is the query I am working on now
select ll.learnerId ,lll.createdAt, (case when interactionType = 'Start' or interactionType = 'Play' then DATEDIFF(SECOND, lll.createdAt, (case when interactionType = 'Stop' or interactionType = 'Pause' then lll.createdAt end) over (order by lll.createdAt desc) ) end) as diff_minutes from learner_lesson_log lll join learner_lessons ll on ll.learnerLessonId = lll.learnerLessonId order by lll.createdAt
But is throwing me the error
SQL Error [1064] [42000]: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘(order by createdAt desc) ) end) as diff_minut’ at line 5
Error position: line: 4
I want the end result to look like this for each learner
learnerid Length of interaction start_timestamp 24 4 2022-11-02 07:51:30 24 11 2022-11-02 07:52:20
Advertisement
Answer
If you’re using MySQL version >= 8.0.14, you can use a LATERAL DERIVED TABLE to get the next createdAt
date that you need to make your comparison in SECONDS
between your interactionType's
.
SELECT c.learnerid AS "Learner ID", TIMESTAMPDIFF(SECOND, a.createdAt, NextDate) AS "Length of Interaction", a.createdAt AS "Start Timestamp" FROM learner_lesson_log a INNER JOIN learner_lessons c ON c.learnerLessonId = a.learnerLessonId, LATERAL ( SELECT b.createdAt AS NextDate, b.interactionType AS NextType FROM learner_lesson_log b INNER JOIN learner_lessons d ON b.learnerLessonId = d.learnerLessonId WHERE b.learnerLessonId = a.learnerLessonId AND d.learnerId = c.learnerId AND b.createdAt > a.createdAt AND b.interactionType IN ('Stop', 'Pause') ORDER BY b.createdAt ASC LIMIT 1 ) bb WHERE a.interactionType IN ('Start', 'Play') ORDER BY a.createdAt ASC;
Fiddle here.
For your version, MySQL version 5.7, use a subquery
in the TIMESTAMPDIFF
calculation:
SELECT c.learnerid AS "Learner ID", TIMESTAMPDIFF(SECOND, a.createdAt, (SELECT b.createdAt FROM learner_lesson_log b INNER JOIN learner_lessons d ON b.learnerLessonId = d.learnerLessonId WHERE b.learnerLessonId = a.learnerLessonId AND d.learnerId = c.learnerId AND b.createdAt > a.createdAt AND b.interactionType IN ('Stop', 'Pause') ORDER BY b.createdAt ASC LIMIT 1)) AS "Length of Interaction", a.createdAt AS "Start Timestamp" FROM learner_lesson_log a INNER JOIN learner_lessons c ON c.learnerLessonId = a.learnerLessonId WHERE a.interactionType IN ('Start', 'Play') ORDER BY a.createdAt ASC;
Fiddle here.
Result:
Learner ID | Length of Interaction | Start Timestamp |
---|---|---|
24 | 4 | 2022-11-02 07:51:30 |
24 | 11 | 2022-11-02 07:52:20 |