Mysql
 sql >> Base de données >  >> RDS >> Mysql

Résumer les données dans un nouveau tableau

Explication étape par étape :

D'abord, vous commandez la table par nom et horodatage et initialisez trois user -variables définies .

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

Comme vous pouvez le voir, nous pouvons utiliser une sous-requête pour cela. Le ORDER BY est important, car il n'y a pas d'ordre dans une base de données relationnelle, sauf si vous le spécifiez.

Maintenant, MySQL évalue le SELECT clause dans l'ordre spécifié, ne modifiez donc pas l'ordre ici.

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

Lorsque vous exécutez cette instruction, vous pouvez voir que lorsque nous sélectionnons simplement les variables, elles contiennent la valeur de la ligne précédente ou NULL lorsque c'est la première ligne qui a été lue. Ensuite, la valeur de la ligne courante est affectée aux variables. Nous pouvons donc maintenant comparer la ligne actuelle avec la ligne précédente. Si quelque chose a changé, nous incrémentons simplement la troisième variable, qui est un nombre pour chaque "groupe" que nous construisons.

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

Nous avons donc incrémenté le @group_number quand quelque chose a changé et s'est assigné la variable si ce n'est pas le cas, pour qu'elle ne change pas.

Maintenant, nous pouvons simplement utiliser cette requête comme sous-requête et faire un regroupement 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