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

Comment trouver les lignes de données manquantes à l'aide de SQL ?

select t1.ts as hival, t2.ts as loval
from metdata t1, metdata t2
where t2.ts = (select max(ts) from metdata t3
where t3.ts < t1.ts)
and not timediff(t1.ts, t2.ts) = '00:10:00'

Cette requête renverra des couplets que vous pouvez utiliser pour sélectionner les données manquantes. Les données manquantes auront un horodatage compris entre hival et loval pour chaque couplet renvoyé par la requête.

EDIT - merci pour la vérification, Craig

EDIT2 :

obtenir les horodatages manquants - ce SQL devient un peu plus difficile à lire, donc je vais le casser un peu. Tout d'abord, nous avons besoin d'un moyen de calculer une série de valeurs d'horodatage entre une valeur basse donnée et une valeur haute dans des intervalles de 10 minutes. Une façon de le faire lorsque vous ne pouvez pas créer de tables est basée sur le sql suivant, qui crée en tant que jeu de résultats tous les chiffres de 0 à 9.

select d1.* from 
(select 1 as digit
union select 2 
union select 3 
union select 4 
union select 5 
union select 6 
union select 7 
union select 8 
union select 9 
union select 0 
) as d1

...maintenant, en combinant ce tableau avec une copie de lui-même plusieurs fois, nous pouvons générer dynamiquement une liste d'une longueur spécifiée

select curdate() + 
INTERVAL  (d1.digit * 100 + d2.digit * 10 + d3.digit) * 10 MINUTE 
as date 
from (select 1 as digit
union select 2 
union select 3 
union select 4 
union select 5 
union select 6 
union select 7 
union select 8 
union select 9 
union select 0 
) as d1
join
(select 1 as digit
union select 2 
union select 3 
union select 4 
union select 5 
union select 6 
union select 7 
union select 8 
union select 9 
union select 0 
) as d2
join
(select 1 as digit
union select 2 
union select 3 
union select 4 
union select 5 
union select 6 
union select 7 
union select 8 
union select 9 
union select 0 
) as d3
where (d1.digit * 100 + d2.digit * 10 + d3.digit) between 1 and 42
order by 1

... maintenant ce morceau de sql se rapproche de ce dont nous avons besoin. Il a 2 variables d'entrée :

  1. un horodatage de début (j'ai utilisé curdate() dans l'exemple) ; et un
  2. nombre d'itérations :la clause where spécifie 42 itérations dans l'exemple, le maximum avec des tables à 3 chiffres est de 1 000 intervalles

... ce qui signifie que nous pouvons utiliser le sql d'origine pour piloter l'exemple ci-dessus afin de générer une série d'horodatages pour chaque paire hival lowval. Soyez patient, ce sql est un peu long maintenant...

select daterange.loval + INTERVAL  (d1.digit * 100 + d2.digit * 10 + d3.digit) * 10 MINUTE as date 
from 
(select t1.ts as hival, t2.ts as loval
from metdata t1, metdata t2
where t2.ts = (select max(ts) from metdata t3
where t3.ts < t1.ts)
and not timediff(t1.ts, t2.ts) = '00:10:00'
) as daterange
join
(select 1 as digit
union select 2 
union select 3 
union select 4 
union select 5 
union select 6 
union select 7 
union select 8 
union select 9 
union select 0 
) as d1
join
(select 1 as digit
union select 2 
union select 3 
union select 4 
union select 5 
union select 6 
union select 7 
union select 8 
union select 9 
union select 0 
) as d2
join
(select 1 as digit
union select 2 
union select 3 
union select 4 
union select 5 
union select 6 
union select 7 
union select 8 
union select 9 
union select 0 
) as d3
where (d1.digit * 100 + d2.digit * 10 + d3.digit) between 1 and
 round((time_to_sec(timediff(hival, loval))-600) /600)
order by 1

...maintenant il y a un peu de sql épique
NOTE :utiliser le tableau des chiffres 3 fois donne un écart maximum qu'il couvrira d'un peu plus de 6 jours