Vysvětlení krok za krokem:
Nejprve si objednáte tabulku podle názvu a časového razítka a inicializujete tři uživatele -definované proměnné .
SELECT s.* FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp
Jak vidíte, můžeme k tomu použít poddotaz. ORDER BY
je důležité, protože v relační databázi neexistuje žádné pořadí, pokud jej neurčíte.
Nyní MySQL vyhodnotí SELECT
doložka v uvedeném pořadí, proto zde pořadí neměňte.
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
Když provedete tento příkaz, můžete vidět, že když jednoduše vybereme proměnné, mají hodnotu předchozího řádku nebo NULL, když je to první řádek, který byl přečten. Poté se proměnným přiřadí hodnota aktuálního řádku. Nyní tedy můžeme porovnat aktuální řádek s předchozím řádkem. Pokud se něco změnilo, jednoduše zvýšíme třetí proměnnou, což je číslo pro každou „skupinu“, kterou vytváříme.
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
Zvýšili jsme tedy @group_number
když se něco změnilo a přiřadil proměnnou sobě, pokud ne, aby se nezměnila.
Nyní můžeme tento dotaz jednoduše použít jako poddotaz a provést jednoduché seskupení.
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
- vidět, jak to funguje v tomto sqlfiddle