Explicação passo a passo:
Primeiro você ordena a tabela por nome e timestamp e inicializa três user -variáveis definidas .
SELECT s.* FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp
Como você pode ver, podemos usar uma subconsulta para isso. O
ORDER BY
é importante, porque não há ordem em um banco de dados relacional, a menos que você a especifique. Agora, o MySQL avalia o
SELECT
cláusula na ordem especificada, portanto, não altere a ordem aqui. 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
Ao executar esta instrução, você pode ver que, quando simplesmente selecionamos as variáveis, elas mantêm o valor da linha anterior ou NULL quando é a primeira linha, que foi lida. Em seguida, o valor da linha atual é atribuído às variáveis. Assim, podemos comparar agora a linha atual com a linha anterior. Se algo mudou, simplesmente incrementamos a terceira variável, que é um número para cada "grupo" que estamos construindo.
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
Então incrementamos o
@group_number
quando algo mudou e atribuiu a variável a si mesma, se não, para que não mude. Agora podemos simplesmente usar essa consulta como subconsulta e fazer um agrupamento simples.
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
- veja-o funcionando neste sqlfiddle