SELECT MIN(classification) AS classification
,MIN(START) AS START
,MAX(next_start) AS END
,SUM(duration) AS seconds
FROM ( SELECT *
, CASE WHEN (duration < 20*60) THEN CASE WHEN (duration = -1) THEN 'current_session' ELSE 'session' END
ELSE 'break'
END AS classification
, CASE WHEN (duration > 20*60) THEN ((@sum_grouping := @sum_grouping +2)-1)
ELSE @sum_grouping
END AS sum_grouping
FROM ( SELECT *
, CASE WHEN next_start IS NOT NULL THEN TIMESTAMPDIFF(SECOND, START, next_start) ELSE -1 END AS duration
FROM ( SELECT id, studentId, START
, (SELECT MIN(START)
FROM attempt AS sub
WHERE sub.studentId = main.studentId
AND sub.start > main.start
) AS next_start
FROM attempt AS main
WHERE main.studentId = 605
ORDER BY START
) AS t1
) AS t2
WHERE duration != 0
) AS t3
GROUP BY sum_grouping
ORDER BY START DESC, END DESC
attempt
表记录了学生在会话期间尝试某些活动。如果两次尝试间隔不到20分钟,我们认为这些尝试是相同的会话。如果他们相隔超过20分钟,我们认为他们休息了一段时间。
我对此查询的目标是采取所有尝试并将其压缩在会话和中断列表中,包括每个会话的开始时间,结束时间(定义为后续会话的开始),以及会议有多长。 classification
是会话,休息还是当前会话。
上面的查询完成了所有这些,但速度太慢了。如何提高性能?
最里面的查询选择尝试的开始时间和后续尝试的开始时间,以及这些值之间的持续时间。
然后,@sum_grouping
和sum_grouping
用于将尝试分成会话和休息时间。 @sum_grouping
仅在尝试超过20分钟(即中断)时才会增加,并且总是增加2.但是,sum_grouping
设置为小于1的值{1}}那&#34;打破&#34;。如果尝试的时间少于20分钟,则使用当前的@sum_grouping
值,而不进行修改。结果,所有中断都是不同的奇数值,并且所有会话(无论是1次还是多次尝试)最终都是不同的偶数。这允许GROUP BY
部分正确地将尝试分为会话和休息。
示例:
Attempt type @sum_grouping sum_grouping
non-break 0 0
non-break 0 0
break 2 1
break 4 3
non-break 4 4
break 6 5
如您所见,所有中断将按sum_grouping
分别用不同的奇数值分组,所有非中断将被组合在一起作为具有偶数值的会话。
MIN(classification)
只是强制&#34;当前会话&#34;两个&#34;会话&#34;和&#34;当前会议&#34;存在于分组的行中。
SHOW CREATE TABLE attempt
CREATE TABLE attempt (
id int(11) NOT NULL AUTO_INCREMENT,
caseId int(11) NOT NULL DEFAULT '0',
eventId int(11) NOT NULL DEFAULT '0',
studentId int(11) NOT NULL DEFAULT '0',
activeUuid char(36) NOT NULL,
start timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
end timestamp NULL DEFAULT NULL,
outcome float DEFAULT NULL,
response varchar(5000) NOT NULL DEFAULT '',
PRIMARY KEY id),
KEY activeUuid activeUuid),
KEY caseId caseId,activeUuid),
KEY end end),
KEY start start),
KEY studentId studentId),
KEY attempt_idx_studentid_stat_id studentId,start,id),
KEY attempt_idx_studentid_stat studentId,start
) ENGINE=MyISAM AUTO_INCREMENT=298382 DEFAULT CHARSET=latin1
答案 0 :(得分:1)
(这不是一个正确的答案,但无论如何都要进行。)
尽量不要嵌套'派生'表。
我看到很多语法错误。
从MyISAM移至InnoDB。
INDEX(a, b)
处理您需要INDEX(a)
的情况,因此DROP
处理后者。