Explicación paso a paso:
Primero ordena la tabla por nombre y marca de tiempo e inicializa tres user variables definidas .
SELECT s.* FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp
Como puede ver, podemos usar una subconsulta para eso. El ORDER BY
es importante, porque no hay orden en una base de datos relacional, a menos que lo especifique.
Ahora, MySQL evalúa el SELECT
cláusula en el orden especificado, por lo tanto, no cambie el orden aquí.
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
Cuando ejecuta esta declaración, puede ver que cuando simplemente seleccionamos las variables, contienen el valor de la fila anterior o NULL cuando es la primera fila que se leyó. Luego, el valor de la fila actual se asigna a las variables. Entonces podemos comparar ahora la fila actual con la fila anterior. Si algo cambió, simplemente incrementamos la tercera variable, que es un número para cada "grupo" que estamos construyendo.
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
Así que incrementamos el @group_number
cuando algo cambió y se asignó la variable si no, para que no cambie.
Ahora podemos simplemente usar esta consulta como subconsulta y hacer una agrupación simple.
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
- ver cómo funciona en este sqlfiddle