It might be faster, but (improving @Roman's 1st solution ).
SELECT id, ts, ct FROM ( SELECT id, ts, ct ,lag (ts, 1, '-infinity') OVER (ORDER BY ts) as prev_ts ,lead(ts, 1, 'infinity') OVER (ORDER BY ts) as next_ts FROM tbl WHERE ct <> 0 ) sub WHERE ct = 1 AND prev_ts < ts - interval '10 min' AND next_ts > ts + interval '10 min' ORDER BY ts;
Handling corner cases "without leading / lagging line" can be greatly simplified by using the following two pieces of information:
Subqueries are generally more efficient than CTEs (some exceptions apply) because CTEs introduce optimization barriers (in design and designation). If performance matters, use CTE only when you need it.
also:
I use the appropriate column names instead of timestamp
and count
, thereby eliminating the need for double quotes. Never use reserved words or base types or function names as identifiers.
None of this has anything to do with plpgsql , which is the default Postgres procedural language.
SQL Fiddle
Index
Since we are dealing with a large table ( > 1 mio rows
) and are only interested in β rare eventsβ, it is important that the performance be a partial index , as shown below:
CREATE INDEX tbl_rare_idx ON tbl(ts) WHERE ct <> 0;
If you are in Postgres 9.2 or later and set some prerequisites, make the coverage index to scan only by index .
CREATE INDEX tbl_rare_covering_idx ON tbl(ts, ct, id) WHERE ct <> 0;
Test with EXPLAIN ANALYZE
to see which query is faster and if the index is being used.
source share