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 into your code and set them as your operator’s parameters. Depending on your client, you can also transfer the initialization of @rownum_start and @rownum_end before the request, which can improve the performance of the requests (you should check that, apart from that, it’s just a gut feeling considering the explanation of both versions)
Here's how it works:
It selects the entire table twice and offset_start each row of offset_start to a row in offset_end that has an offset of @num_occurences . (This is done using @rownum_* variables to create an index for each row that mimics the row_number () function, known from other rdbms).
Then it simply checks to see if two lines refer to the same object_id and satisfy the requirements of the period.
Since this is done for each line of occurrence, object_id will be returned several times if the number of occurrences is actually greater than @max_occurences , so it is grouped at the end to return the returned object_id unique
ddelbondio
source share