This should work:
SET @num_occurences = 7; -- how many occurences should occur in the interval
SET @max_period = 10; -- your interval in seconds
SELECT offset_start.object_id FROM
(SELECT @rownum_start := @rownum_start+1 AS idx, object_id, seen_timestamp
FROM occurences, (SELECT @rownum_start:=0) r ORDER BY object_id ASC, seen_timestamp ASC) offset_start
JOIN
(SELECT @rownum_end := @rownum_end + 1 AS idx, object_id, seen_timestamp
FROM occurences, (SELECT @rownum_end:=0) r ORDER BY object_id ASC, seen_timestamp ASC) offset_end
ON offset_start.object_id = offset_end.object_id
AND offset_start.idx + @num_occurences - 1 = offset_end.idx
AND offset_end.seen_timestamp - offset_start.seen_timestamp <= @max_period
GROUP BY offset_start.object_id;
You can move @num_occurences
and @num_occurences
to your code and set these as parameters of your statement. Depending on your client you can also move the the initialisation of @rownum_start
and @rownum_end
in front of the query, that might improve the query performance (you should test that nontheless, just a gut feeling looking at the explain of both versions)
Here's how it works:
It selects the entire table twice and joins each row of offset_start
with the row in offset_end
which has an offset of @num_occurences
. (This is done using the @rownum_*
variables to create the index of each row, simulating row_number() functionality known from other rdbms).
Then it just checks whether the two rows refer to the same object_id and satisfy the period requirements.
Since this is done for every occurence row, the object_id would be returned multiple times if the number of occurences is actually larger than @max_occurences
, so it's grouped in the end to make the returned object_id
s unique