Stap voor stap uitleg:
Eerst bestelt u de tabel op naam en tijdstempel en initialiseert u drie gebruiker -gedefinieerde variabelen .
SELECT s.* FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp
Zoals je kunt zien, kunnen we daarvoor een subquery gebruiken. De ORDER BY
is belangrijk, omdat er geen volgorde is in een relationele database, tenzij u deze specificeert.
Nu evalueert MySQL de SELECT
clausule in de opgegeven volgorde, dus wijzig de volgorde hier niet.
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
Wanneer u deze instructie uitvoert, kunt u zien dat wanneer we eenvoudig de variabelen selecteren, ze de waarde van de vorige rij bevatten of NULL wanneer het de eerste rij is, die werd gelezen. Vervolgens wordt de waarde van de huidige rij aan de variabelen toegewezen. We kunnen nu dus de huidige rij vergelijken met de vorige rij. Als er iets verandert, verhogen we gewoon de derde variabele, wat een getal is voor elke "groep" die we aan het bouwen zijn.
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
Dus hebben we de @group_number
. verhoogd wanneer iets veranderde en de variabele aan zichzelf toegewezen, zo niet, zodat het niet verandert.
Nu kunnen we deze zoekopdracht eenvoudig als subquery gebruiken en een eenvoudige groepering uitvoeren.
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
- zie hoe het werkt in deze sqlfiddle