Schritt-für-Schritt-Erklärung:
Zuerst ordnet man die Tabelle nach Namen und Zeitstempel und initialisiert drei Benutzer -definierte Variablen .
SELECT s.* FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp
Wie Sie sehen können, können wir dafür eine Unterabfrage verwenden. Der ORDER BY
ist wichtig, da es in einer relationalen Datenbank keine Reihenfolge gibt, es sei denn, Sie geben sie an.
Nun wertet MySQL den SELECT
aus -Klausel in der angegebenen Reihenfolge, ändern Sie daher die Reihenfolge hier nicht.
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
Wenn Sie diese Anweisung ausführen, können Sie sehen, dass, wenn wir die Variablen einfach auswählen, sie den Wert der vorherigen Zeile oder NULL enthalten, wenn es die erste Zeile ist, die gelesen wurde. Dann wird den Variablen der Wert der aktuellen Zeile zugewiesen. So können wir jetzt die aktuelle Zeile mit der vorherigen Zeile vergleichen. Wenn sich etwas geändert hat, erhöhen wir einfach die dritte Variable, die eine Zahl für jede "Gruppe" ist, die wir erstellen.
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
Also haben wir @group_number
erhöht wenn sich etwas geändert hat und die Variable sich selbst zugewiesen hat, wenn nicht, damit sie sich nicht ändert.
Jetzt können wir diese Abfrage einfach als Unterabfrage verwenden und eine einfache Gruppierung vornehmen.
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
- Sehen Sie, wie es in diesem sqlfiddle funktioniert