分步说明:
首先您按名称和时间戳对表进行排序并初始化三个user-defined variables。
SELECT s.* FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp
如您所见,我们可以为此使用子查询。 ORDER BY 很重要,因为关系数据库中没有顺序,除非您指定它。
现在,MySQL 以指定的顺序评估 SELECT 子句,因此不要在此处更改顺序。
SELECT
s.*,
@prevName,
@prevStatus,
@prevName := s.name,
@prevStatus := s.status
FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp
当您执行此语句时,您可以看到,当我们简单地选择变量时,它们保存前一行的值,或者当它是第一行时为 NULL,即被读取。然后将当前行的值分配给变量。所以我们现在可以将当前行与前一行进行比较。如果发生了变化,我们只需增加第三个变量,它是我们正在构建的每个“组”的数字。
SELECT
s.*,
@group_number := IF(@prevName != s.name OR @prevStatus != s.status, @group_number + 1, @group_number) AS group_number,
@prevName := s.name,
@prevStatus := s.status
FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp
所以我们在发生变化时增加了@group_number,如果没有变化,我们将变量分配给自身,这样它就不会改变。
现在我们可以简单地将此查询用作子查询并进行简单的分组。
SELECT
group_number AS id,
name,
status,
MIN(error) AS error,
MIN(timestamp) AS firstEntry,
MAX(timestamp) AS lastEntry,
COUNT(*) AS entries
FROM (
SELECT
s.*,
@group_number := IF(@prevName != s.name OR @prevStatus != s.status, @group_number + 1, @group_number) AS group_number,
@prevName := s.name,
@prevStatus := s.status
FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp
) sq
GROUP BY
group_number,
name,
status