Хорошо, я понимаю, что я немного поздно, но я хотел отправить свой ответ в любом случае :-)
Что вам требуется может быть сделано с использованием подзапроса, но это может занять возрастов, чтобы закончить на большой стол ...
Думая о вопросе, я пришел к двум различным подходам.
Один из них уже рассмотрен в других ответах, он работает, начиная с определенного момента времени, глядя на интервал, который начинается в это время, а затем смотрит на промежуток равной продолжительности, который следует за ним сразу. Это приводит к ясным, понятным результатам и, вероятно, потребует (например, пользователь не должен превышать 100 загрузок за календарный день). Это, однако, полностью упустило бы ситуации, когда пользователь делает 99 загрузок за час до полуночи и еще 99 в первый час нового дня.
Так что, если требуемый результат является скорее «списком лучших десятков», то это другой подход. Результаты здесь могут быть не столь понятными с первого взгляда, потому что одна загрузка может рассчитывать на несколько интервалов. Это связано с тем, что интервалы будут (и должны) перекрываться.
Вот мои настройки.Я создал таблицу из вашего заявления и добавлен два индекса:
CREATE INDEX downloads_timestamp on downloads (dl_date);
CREATE INDEX downloads_user_id on downloads (user_id);
данные, которые я вставил в таблицу:
SELECT * FROM downloads;
+----+----------+---------+---------------------+
| id | stuff_id | user_id | dl_date |
+----+----------+---------+---------------------+
| 1 | 1 | 1 | 2011-01-24 09:00:00 |
| 2 | 1 | 1 | 2011-01-24 09:30:00 |
| 3 | 1 | 1 | 2011-01-24 09:35:00 |
| 4 | 1 | 1 | 2011-01-24 10:00:00 |
| 5 | 1 | 1 | 2011-01-24 11:00:00 |
| 6 | 1 | 1 | 2011-01-24 11:15:00 |
| 7 | 1 | 1 | 2011-01-25 09:15:00 |
| 8 | 1 | 1 | 2011-01-25 09:30:00 |
| 9 | 1 | 1 | 2011-01-25 09:45:00 |
| 10 | 1 | 2 | 2011-01-24 08:00:00 |
| 11 | 1 | 2 | 2011-01-24 12:00:00 |
| 12 | 1 | 2 | 2011-01-24 12:01:00 |
| 13 | 1 | 2 | 2011-01-24 12:02:00 |
| 14 | 1 | 2 | 2011-01-24 12:03:00 |
| 15 | 1 | 2 | 2011-01-24 12:00:00 |
| 16 | 1 | 2 | 2011-01-24 12:04:00 |
| 17 | 1 | 2 | 2011-01-24 12:05:00 |
| 18 | 1 | 2 | 2011-01-24 12:06:00 |
| 19 | 1 | 2 | 2011-01-24 12:07:00 |
| 20 | 1 | 2 | 2011-01-24 12:08:00 |
| 21 | 1 | 2 | 2011-01-24 12:09:00 |
| 22 | 1 | 2 | 2011-01-24 12:10:00 |
| 23 | 1 | 2 | 2011-01-25 14:00:00 |
| 24 | 1 | 2 | 2011-01-25 14:12:00 |
| 25 | 1 | 2 | 2011-01-25 14:25:00 |
+----+----------+---------+---------------------+
25 rows in set (0.00 sec)
Как вы можете видеть, все загрузки произошла ни вчера, ни сегодня и выполнялись двумя разными пользователями.
Теперь мы должны иметь в виду следующее: существует математически бесконечное количество интервалов в 24 часа (или интервалы любой другой продолжительности) между '2011-01-24 0:00' и '2011- 01-25 23:59:59 '. Но точность сервера, составляет одну секунду, это сводится к 86400 интервалов:
First interval: 2011-01-24 0:00:00 -> 2011-01-25 0:00:00
Second interval: 2011-01-24 0:00:01 -> 2011-01-25 0:00:01
Third interval: 2011-01-24 0:00:02 -> 2011-01-25 0:00:02
.
.
.
86400th interval: 2011-01-24 23:59:59 -> 2011-01-25 23:59:59
Таким образом, мы могли бы использовать цикл для перебора всех этих интервалов и вычислить количество загрузок для каждого пользователя и за интервал. Конечно, не все интервалы представляют для нас такой же интерес, поэтому мы можем пропустить некоторые из них, используя временные метки в таблице как «начало интервала».
Это то, что делает следующий запрос. Он использует каждую временную метку загрузки в таблице как «начало интервала», добавляет продолжительность интервала и затем запрашивает количество загрузок на пользователя за этот интервал.
SET @duration = '24:00:00';
SET @limit = 5;
SELECT * FROM
(SELECT t1.user_id,
t1.dl_date startOfPeriod,
ADDTIME(t1.dl_date,@duration) endOfPeriod,
(SELECT COUNT(1)
FROM downloads t2
WHERE t1.user_id = t2.user_id
AND t1.dl_date <= t2.dl_date
AND ADDTIME(t1.dl_date,@duration) >= t2.dl_date) count
FROM downloads t1) t3
WHERE count > @limit;
Вот результат:
+---------+---------------------+---------------------+-------+
| user_id | startOfPeriod | endOfPeriod | count |
+---------+---------------------+---------------------+-------+
| 1 | 2011-01-24 09:00:00 | 2011-01-25 09:00:00 | 6 |
| 1 | 2011-01-24 09:30:00 | 2011-01-25 09:30:00 | 7 |
| 1 | 2011-01-24 09:35:00 | 2011-01-25 09:35:00 | 6 |
| 1 | 2011-01-24 10:00:00 | 2011-01-25 10:00:00 | 6 |
| 2 | 2011-01-24 08:00:00 | 2011-01-25 08:00:00 | 13 |
| 2 | 2011-01-24 12:00:00 | 2011-01-25 12:00:00 | 12 |
| 2 | 2011-01-24 12:01:00 | 2011-01-25 12:01:00 | 10 |
| 2 | 2011-01-24 12:02:00 | 2011-01-25 12:02:00 | 9 |
| 2 | 2011-01-24 12:03:00 | 2011-01-25 12:03:00 | 8 |
| 2 | 2011-01-24 12:00:00 | 2011-01-25 12:00:00 | 12 |
| 2 | 2011-01-24 12:04:00 | 2011-01-25 12:04:00 | 7 |
| 2 | 2011-01-24 12:05:00 | 2011-01-25 12:05:00 | 6 |
+---------+---------------------+---------------------+-------+
12 rows in set (0.00 sec)
Если этот запрос принимает одну метку времени, как «начало периода», вычислить «конец периода» и список всех пользователей, которые превосходили количество загрузок в этот период, или должен ли он перечислять всех пользователей, которые когда-либо превышали загрузку x за 24 часа? –
@Patrick нет начального или конечного периода ... просто укажите всех пользователей, которые превышают загрузку X в Y (как период времени, который может быть чем-то отличным от 24 часов). Ограничение времени – eduardev
Я думал о (возможном) решении. Если вы все еще заинтересованы, я поработаю и опубликую его здесь, но у него будет недостаток: представьте, что я делаю 100 загрузок всего за один час, тогда будет много периодов, в которых я превышу лимит. Пример: 100 загрузок сегодня с 8 до 9 утра. Вчера 9:00 до сегодняшнего дня 9 AM = 100 загрузок. Вчера 10:00 до сегодняшнего дня 10 AM = 100 загрузок. Вчера 11:00 до сегодняшнего дня 11 AM = 100 загрузок. Продолжение следует ... –