OK, zdaję sobie sprawę, że jestem trochę spóźniony, ale i tak chciałem opublikować swoją odpowiedź :-)
To, czego potrzebujesz, można wykonać za pomocą podzapytania, ale może to zająć wieki na dużym stole...
Zastanawiając się nad pytaniem doszedłem do dwóch różnych podejść.
Jeden z nich został już omówiony w innych odpowiedziach, działa on zaczynając od określonego punktu w czasie, patrząc na przedział, który zaczyna się w tym czasie, a następnie patrząc na przedział o równym czasie trwania, który następuje bezpośrednio. Prowadzi to do jasnych, zrozumiałych wyników i prawdopodobnie jest to wymagane (np. użytkownik nie może przekraczać 100 pobrań na dzień kalendarzowy). To jednak całkowicie pomija sytuacje, w których użytkownik pobiera 99 pobrań w ciągu godziny przed północą i kolejne 99 w pierwszej godzinie nowego dnia.
Więc jeśli wymagany wynik jest bardziej „listą dziesięciu najlepszych pobierających”, to jest to inne podejście. Wyniki tutaj mogą nie być tak zrozumiałe na pierwszy rzut oka, ponieważ jedno pobranie może wliczać się do wielu interwałów. Dzieje się tak, ponieważ interwały będą (i będą musiały) zachodzić na siebie.
Oto moja konfiguracja. Stworzyłem tabelę z Twojego wyciągu i dodałem dwa indeksy:
CREATE INDEX downloads_timestamp on downloads (dl_date);
CREATE INDEX downloads_user_id on downloads (user_id);
Dane, które wstawiłem do tabeli:
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)
Jak widać, wszystkie pobrania miały miejsce wczoraj lub dzisiaj i zostały wykonane przez dwóch różnych użytkowników.
Teraz musimy pamiętać, że istnieje (matematycznie) nieskończona liczba 24-godzinnych interwałów (lub interwałów o dowolnym innym czasie trwania) między '2011-01-24 0:00' a '2011-01-25 23 :59:59”. Ale ponieważ precyzja serwera wynosi jedną sekundę, sprowadza się to do 86 400 interwałów:
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
Moglibyśmy więc użyć pętli do iteracji we wszystkich tych interwałach i obliczenia liczby pobrań na użytkownika i na interwał. Oczywiście nie wszystkie interwały nas interesują, więc możemy pominąć niektóre z nich, używając znaczników czasu w tabeli jako „początku interwału”.
To właśnie robi poniższe zapytanie. Wykorzystuje każdy znacznik czasu pobierania w tabeli jako „początek interwału”, dodaje czas trwania interwału, a następnie pyta o liczbę pobrań na użytkownika w tym interwale.
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;
Oto wynik:
+---------+---------------------+---------------------+-------+
| 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)