OK, zdaję sobie sprawę, że jestem trochę późno, ale chciałem pisać moją odpowiedź w każdym razie :-)
Czego wymagać można zrobić za pomocą podzapytania, ale może to trwać wieki, aby zakończyć na dużą table ...
Myśląc o tym pytaniu doszedłem do dwóch różnych podejść.
Jeden z nich został już rozwiązany w innych odpowiedziach, działa od początku w określonym momencie, patrząc na interwał, który rozpoczyna się w tym czasie, a następnie patrząc na przedział równego czasu 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 przekroczyć 100 pobrań w danym dniu kalendarzowym). To jednak całkowicie pomijane sytuacje, w których użytkownik robi 99 pobrań w ciągu godziny przed północą i kolejne 99 w pierwszej godzinie nowego dnia.
Jeśli więc wymagany wynik jest bardziej "pierwszą dziesiątą listy downloaderów", to jest to inne podejście. Wyniki mogą nie być tak zrozumiałe na pierwszy rzut oka, ponieważ jedno pobranie może liczyć się w wielu odstępach czasu. Dzieje się tak dlatego, że odstępy będą (i muszą) pokrywać się.
Oto moja konfiguracja.Utworzyłem tabelę z wyciągu i dodał dwa indeksy:
CREATE INDEX downloads_timestamp on downloads (dl_date);
CREATE INDEX downloads_user_id on downloads (user_id);
dane mam wstawiony 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 pliki do pobrania albo wystąpił wczoraj lub dzisiaj i zostały wykonane przez dwóch różnych użytkowników.
Teraz mamy następujące zdanie: Istnieje (matematycznie) nieskończona liczba interwałów 24-godzinnych (lub interwałów o dowolnym innym czasie trwania) między "2011-01-24 0:00" a "2011- 01-25 23:59:59 ". Ale jak precyzja serwera wynosi jedną sekundę, to sprowadza się do 86,400 odstępach:
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
Więc możemy użyć pętli iteracyjne nad wszystkich tych przedziałów i obliczyć liczbę pobrań na użytkownika i na przedziale. Oczywiście nie wszystkie interwały są dla nas tym samym zainteresowaniem, więc możemy pominąć niektóre z nich, używając znaczników czasu w tabeli jako "początek interwału".
Oto, co 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 zapytuje o liczbę pobrań na użytkownika w tym przedziale.
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)
Gdyby tak zapytania przyjąć jeden znacznik czasu jako „początek okresu” oblicz „koniec okresu” i listę wszystkich użytkowników, którzy przekroczyli ilości pobrań w tym okresie, lub czy powinien on zawierać listę wszystkich użytkowników, którzy przekroczyli limit pobierania x na 24 godziny? –
@Patrick bez okresu początkowego ani końcowego ... po prostu wymień wszystkich użytkowników, którzy przekroczyli X pobrań w Y (jako okres, który może być inny niż 24 godziny) limit czasowy – eduardev
Myślałem o (możliwym) rozwiązaniu. Jeśli nadal jesteś zainteresowany, opracuję go i opublikuję tutaj, ale będzie to miało wadę: Wyobraź sobie, że robię 100 pobrań w ciągu zaledwie jednej godziny, wtedy będzie wiele okresów, w których przekroczę limit. Np. 100 pobrań dzisiaj od 8 do 9 rano. Wczoraj 9 rano do dziś 9 rano = 100 pobrań. Wczoraj 10 rano do dziś 10 rano = 100 pobrań. Wczoraj 11 rano do dziś 11 rano = 100 pobrań. Ciąg dalszy nastąpi ... –