Mysql
 sql >> Database >  >> RDS >> Mysql

Riepiloga i dati in una nuova tabella

Spiegazione passo passo:

Per prima cosa ordini la tabella per nome e timestamp e inizializzi tre utente -variabili definite .

SELECT s.* FROM status_table s
, (SELECT @group_number := 0, @prevName := NULL, @prevStatus := NULL) var_init_subquery
ORDER BY name, timestamp

Come puoi vedere, possiamo usare una sottoquery per questo. Il ORDER BY è importante, perché non c'è ordine in un database relazionale, a meno che tu non lo specifichi.

Ora MySQL valuta SELECT clausola nell'ordine specificato, pertanto non modificare l'ordine qui.

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

Quando esegui questa istruzione, puoi vedere che quando selezioniamo semplicemente le variabili mantengono il valore della riga precedente o NULL quando è la prima riga, quella è stata letta. Quindi il valore della riga corrente viene assegnato alle variabili. Quindi possiamo confrontare ora la riga corrente con la riga precedente. Se qualcosa è cambiato, incrementiamo semplicemente la terza variabile, che è un numero per ogni "gruppo" che stiamo costruendo.

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

Quindi abbiamo incrementato il @group_number quando qualcosa è cambiato e si è assegnata la variabile in caso contrario, in modo che non cambi.

Ora possiamo semplicemente usare questa query come sottoquery ed eseguire un semplice raggruppamento.

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