Reputation: 56
I have a sqlite table with timestamps in milliseconds as primary key each row should be 1 second or 1000 apart from one another. Sometimes my data recorder goes out and there is no data in the table for that time. How can I find the gaps using a SQL statement? A cursor based solution is possible I know.
table = PVT
TS
1119636081000
1119636082000
1119636083000
1119636084000
1119636085000
------gap------
1119636090000
1119636091000
Upvotes: 2
Views: 1067
Reputation: 7083
Create a tally table with at least 86400 rows (one per second for a day):
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;
Join your PVT table onto the transposed records for the day:
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;
Given a table I populated with your sample data I get this as an output:
Expected TS
------------- -------------
1119636081000 1119636081000
1119636082000 1119636082000
1119636083000 1119636083000
1119636084000 1119636084000
1119636085000 1119636085000
1119636086000
1119636087000
1119636088000
1119636089000
1119636090000 1119636090000
1119636091000 1119636091000
1119636092000
1119636093000
1119636094000
1119636095000
If you then additionally filter where PVT.TS is null, you should get the missing values:
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
NOTE: I'm using limit 15 to keep myself sane at the console
Upvotes: 0
Reputation: 1933
This may work. Assuming the table name is "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)
Another way
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
)
Using MINUS operator. I am not sure, which of these queries does better performance wise.
select ts+1000
from pvt
where ts != (select max(ts) from pvt)
minus
select ts
from pvt
where ts != (select min(ts) from pvt)
Upvotes: 2
Reputation: 58681
At the time of this writing SQLite does not support window functions like LAG(TS) OVER (ORDER BY TS ASC)
nor LEAD() OVER
, which would easily give you the previous and following TS
values, respectively.
So, you need to do it yourself:
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);
This will give you something like this (I used different data, as you'll see):
-- 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)
You can always restrict that query to only those records WHERE prev.TS IS NULL OR next.TS is NULL
, too.
Upvotes: 0
Reputation: 63
Something like this (Assuming PVT.TS is your Column name):
SELECT * FROM 'table' WHERE PVT.TS ISNULL;
or
SELECT * FROM 'table' WHERE PVT.TS IS NULL;
If your collector is actually entering a blank entry you might need
WHERE PVT.TS = ''
or
where ifnull(some_column, '') = ''
Upvotes: 0