Mysql
 sql >> Baza danych >  >> RDS >> Mysql

mysql wybierz liczbę wierszy w przedziale czasowym

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)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySql — Sequalize — Nie można dodać ograniczenia klucza obcego

  2. Szybkie spojrzenie na funkcje numeryczne SQL Server

  3. Group_Concat w Concat nie działa z wartościami NULL

  4. Konwersja wierszy ze zbyt dużą liczbą wartości na kolumny

  5. Klucze obce — co dla mnie robią?