Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como encontrar linhas de dados ausentes usando 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'

Essa consulta retornará dísticos que você pode usar para selecionar os dados ausentes. Os dados ausentes terão um timestamp entre hival e loval para cada dístico retornado pela consulta.

EDIT - thx para verificar, Craig

EDIT2:


obtendo os timestamps ausentes - esse SQL fica um pouco mais difícil de ler, então vou dividi-lo um pouco. Primeiro, precisamos de uma maneira de calcular uma série de valores de carimbo de data/hora entre um determinado valor baixo e um valor alto em intervalos de 10 minutos. Uma maneira de fazer isso quando você não pode criar tabelas é baseada no sql a seguir, que cria como resultado todos os dígitos de 0 a 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

...agora, combinando esta tabela com uma cópia de si mesma algumas vezes significa que podemos gerar dinamicamente uma lista de um comprimento especificado
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

... agora esse pedaço de sql está chegando perto do que precisamos. Possui 2 variáveis ​​de entrada:
  1. um timestamp inicial (useicurdate() no exemplo); e um
  2. número de iterações - a cláusula where especifica 42 iterações no exemplo, o máximo com tabelas de 3 x dígitos é de 1.000 intervalos

... o que significa que podemos usar o sql original para conduzir o exemplo acima para gerar uma série de timestamps para cada par hival lowval. Tenha paciência comigo, este sql é um pouco longo agora ...
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

...agora há um pouco de sql épico
NOTA:usar a tabela de dígitos 3 vezes fornece uma lacuna máxima que cobrirá um pouco mais de 6 dias