sql >> Base de Datos >  >> RDS >> Mysql

Resumir datos en una nueva tabla

Explicación paso a paso:

Primero ordena la tabla por nombre y marca de tiempo e inicializa tres user variables definidas .

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

Como puede ver, podemos usar una subconsulta para eso. El ORDER BY es importante, porque no hay orden en una base de datos relacional, a menos que lo especifique.

Ahora, MySQL evalúa el SELECT cláusula en el orden especificado, por lo tanto, no cambie el orden aquí.

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

Cuando ejecuta esta declaración, puede ver que cuando simplemente seleccionamos las variables, contienen el valor de la fila anterior o NULL cuando es la primera fila que se leyó. Luego, el valor de la fila actual se asigna a las variables. Entonces podemos comparar ahora la fila actual con la fila anterior. Si algo cambió, simplemente incrementamos la tercera variable, que es un número para cada "grupo" que estamos construyendo.

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

Así que incrementamos el @group_number cuando algo cambió y se asignó la variable si no, para que no cambie.

Ahora podemos simplemente usar esta consulta como subconsulta y hacer una agrupación simple.

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