鉴于该表,我正在尝试选择记录组并对每个组中的最后一列Class
求和。分组的规则稍微复杂,行需要相互比较。
|| Seq || Time || Spec || Class
|| 1 || 8:05 || 0 || 5
|| 2 || 8:06 || 1 || 5
|| 3 || 8:07 || 2 ||10
|| 4 || 8:08 || 4 ||10
|| 5 || 8:09 || 3 || 5
|| 6 || 8:10 || 2 || 5
|| 7 || 8:11 || 6 || 5
|| 8 || 8:12 || 6 ||15
我需要根据Spec
列中值的变化(增加或减少)对记录进行分组。所需的值更改为2.因此从第1行开始,Spec
为0
。它在第3行之前不会增加至少2
。这是一个有效的组,我需要对Class
字段求和。预期输出为StartTime
,StartSpec
,EndTime
,EndSpec
和TotalClass
。
要确定下一组,我需要使用上一组中使用的最后一行来衡量值的变化。如您所见,第4行立即增加了2,因此这一行是一个有效的组。
预期产出:
||StartTime || StartSpec || EndTime || EndSpec || TotalClass
|| 8:05 || 0 || 8:07 || 2 || 20
|| 8:08 || 4 || 8:08 || 4 || 10
|| 8:09 || 3 || 8:10 || 2 || 10
|| 8:11 || 6 || 8:11 || 6 || 5
答案 0 :(得分:1)
可以通过使用一些中间变量来检测组中的第一行和最后一行,如下所示。
请注意,如果最后一组尚未关闭,这将“自动关闭”。
另请注意,对于像这样的用例,应用程序级解决方案 可能是一个更优雅的选择(如评论中所述)。
另一种选择是在数据插入时计算显式组鉴别器(即“gid”),并将其存储在表本身中,这样您就可以以标准方式查询数据,而不依赖于任何变量。
SELECT
MAX(startTime) as startTime,
MAX(startSpec) as startSpec,
MAX(endTime) as endTime,
MAX(endSpec) as endSpec,
SUM(class) as totalClass
FROM (
SELECT
/* Detect first and last rows in a group (when ordered by "seq") */
@first as isFirst,
@last:=(ABS(@prev-spec)>1 OR seq=(SELECT MAX(seq) FROM groups)) as isLast,
/* If this is a first row, set "startTime" and "startSpec" */
IF(@first,time,NULL) as startTime,
IF(@first,spec,NULL) as startSpec,
/* If this is a last row, set "endTime" and "endSpec" */
IF(@last,time,NULL) as endTime,
IF(@last,spec,NULL) as endSpec,
/* Start the next group */
IF(@last,@prev:=spec,NULL) as nextPrev,
IF(@last,(@gid:=@gid+1)-1,@gid) as gid,
/* Flip "first" */
@first:=@last as nextIsFirst,
/* Row "class" */
class
FROM
/* Declare some variables */
(SELECT @first:=TRUE,@last:=FALSE,@prev:=0,@gid:=0) init
CROSS JOIN Groups ORDER BY seq
) labeled GROUP BY gid;