Wyjaśnienie krok po kroku:
Najpierw uporządkuj tabelę według nazwy i znacznika czasu oraz zainicjuj trzy użytkownik -definiowane zmienne .
SELECT s.* FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp
Jak widać, możemy do tego użyć podzapytania. ORDER BY
jest ważne, ponieważ w relacyjnej bazie danych nie ma porządku, chyba że go określisz.
Teraz MySQL ocenia SELECT
klauzuli w określonej kolejności, dlatego nie zmieniaj tutaj kolejności.
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
Kiedy wykonasz tę instrukcję, możesz zobaczyć, że kiedy po prostu wybieramy zmienne, przechowują one wartość poprzedniego wiersza lub NULL, gdy jest to pierwszy odczytany wiersz. Następnie do zmiennych przypisywana jest wartość bieżącego wiersza. Możemy więc teraz porównać bieżący wiersz z poprzednim. Jeśli coś się zmieniło, po prostu zwiększamy trzecią zmienną, która jest liczbą dla każdej „grupy”, którą budujemy.
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
Dlatego zwiększyliśmy @group_number
kiedy coś się zmieniło i przypisał zmienną do siebie, jeśli nie, aby to się nie zmieniło.
Teraz możemy po prostu użyć tego zapytania jako podzapytania i wykonać proste grupowanie.
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
- zobacz, jak działa w tym sqlfiddle