Обяснение стъпка по стъпка:
Първо подреждате таблицата по име и времева марка и инициализирате три потребител -дефинирани променливи .
SELECT s.* FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp
Както можете да видите, можем да използваме подзаявка за това. ORDER BY
е важно, защото няма ред в релационна база данни, освен ако не го посочите.
Сега MySQL оценява SELECT
клауза в посочения ред, затова не променяйте реда тук.
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
Когато изпълните този израз, можете да видите, че когато просто изберем променливите, те държат стойността на предишния ред или NULL, когато е първият ред, който е прочетен. След това стойността на текущия ред се присвоява на променливите. Така че можем да сравним сега текущия ред с предишния ред. Ако нещо се промени, ние просто увеличаваме третата променлива, която е число за всяка „група“, която изграждаме.
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
Така че увеличихме @group_number
когато нещо се промени и присвои променливата на себе си, ако не, така че да не се промени.
Сега можем просто да използваме тази заявка като подзаявка и да направим просто групиране.
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
- вижте как работи в този sqlfiddle