如何在sqlite表中找到差距?

时间:2015-07-23 14:08:03

标签: sql sqlite gaps-and-islands

我有一个带有时间戳的sqlite表(以毫秒为单位)作为主键,每行应该是1秒或1000彼此分开。有时我的数据记录器熄灭,那时表中没有数据。如何使用SQL语句找到差距?我知道可以使用基于游标的解决方案。

table = PVT
TS
1119636081000
1119636082000
1119636083000
1119636084000
1119636085000
------gap------
1119636090000
1119636091000

4 个答案:

答案 0 :(得分:2)

这可能有用。假设表名是“tstamps”,

select a.ts
from tstamps a
where not exists
   (select b.ts
    from tstamps b
    where b.ts = a.ts+1000)
and exists
   (select c.ts
    from tstamps c
    where c.ts = a.ts+2000)

另一种方式

select a.ts
from tstamps a
where not exists
   (select b.ts
    from tstamps b
    where b.ts = a.ts+1000)
and a.ts <
   (select max(c.ts)
    from tstamps c
   )

使用MINUS运算符。我不确定,哪些查询的性能更好。

select ts+1000
from pvt
where ts != (select max(ts) from pvt)
minus
select ts
from pvt
where ts != (select min(ts) from pvt)

答案 1 :(得分:0)

这样的事情(假设PVT.TS是你的专栏名称):

SELECT * FROM 'table' WHERE PVT.TS ISNULL;

SELECT * FROM 'table' WHERE PVT.TS IS NULL;

如果您的收藏家实际上正在输入空白条目,则可能需要

WHERE PVT.TS = ''

where ifnull(some_column, '') = ''

答案 2 :(得分:0)

在撰写本文时,SQLite不支持LAG(TS) OVER (ORDER BY TS ASC)LEAD() OVER等窗口函数,它们可以轻松地分别为您提供上一个和后面的TS值。

所以,你需要自己做:

sqlite> .mode col
sqlite> .width 14 14 14
sqlite>    SELECT PVT.TS  AS measurement,
                  prev.TS AS prev,
                  next.TS AS next
             FROM PVT
        LEFT JOIN PVT next ON PVT.TS = (next.TS - 1000)
        LEFT JOIN PVT prev ON PVT.TS = (prev.TS + 1000);

这会给你这样的东西(我使用了不同的数据,正如你所见):

-- measurement        prev            next     
  -------------   -------------   -------------
  1119636081000                   1119636082000   -- gap (no previous at all)
  1119636082000   1119636081000   1119636083000 
  1119636083000   1119636082000   1119636084000 
  1119636084000   1119636083000   1119636085000 
  1119636085000   1119636084000                   -- gap (no next offset 1000)
  1119636088000                   1119636089000   -- gap (no previous offset 1000)
  1119636089000   1119636088000                   -- gap (no next at all)

您始终可以将该查询仅限制为那些记录WHERE prev.TS IS NULL OR next.TS is NULL

答案 3 :(得分:0)

创建一个至少有86400行的计数表(一天一次):

create table Tally(n integer primary key not null);
insert into Tally(n) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
insert into Tally(n) select null from tally n1 , tally n2, tally n3, tally n4, tally n5;

将您的PVT表加入到当天的转置记录中:

select 1119636081000 + tally.n*1000 as Expected, pvt.ts from tally left join pvt on pvt.ts = 1119636081000 + tally.n*1000 where tally.n <= 86400 limit 15;

给定一个用我的样本数据填充的表格,我将其作为输出:

Expected       TS
-------------  -------------
1119636081000  1119636081000
1119636082000  1119636082000
1119636083000  1119636083000
1119636084000  1119636084000
1119636085000  1119636085000
1119636086000
1119636087000
1119636088000
1119636089000
1119636090000  1119636090000
1119636091000  1119636091000
1119636092000
1119636093000
1119636094000
1119636095000

如果你再过滤PVT.TS为空的地方,你应该得到缺失值:

select 1119636081000 + tally.n*1000 as Expected, pvt.ts from tally left join pvt on pvt.ts = 1119636081000 + tally.n*1000 where tally.n <= 86400 and PVT.ts is null limit 15;

Expected       TS
-------------  ----------
1119636086000
1119636087000
1119636088000
1119636089000
1119636092000
1119636093000
1119636094000
1119636095000
1119636096000
1119636097000
1119636098000
1119636099000
1119636100000
1119636101000
1119636102000

注意:我使用限制15来保持自己对控制台的理智