sql >> Database teknologi >  >> RDS >> Mysql

mysql vælg antal rækker mellem tidsrum

OK, jeg er klar over, at jeg er lidt forsinket, men jeg ville alligevel sende mit svar :-)

Det, du har brug for, kan gøres ved hjælp af en underforespørgsel, men det kan tage evigheder at gennemføre på et stort bord...

Da jeg tænkte over spørgsmålet, kom jeg til to forskellige tilgange.

En af dem er allerede blevet behandlet i de andre svar, det virker ved at starte på et bestemt tidspunkt, se på det interval, der begynder på dette tidspunkt, og så på det interval af samme varighed, der umiddelbart følger. Dette fører til klare, forståelige resultater og er sandsynligvis det, der kræves (f.eks. må brugeren ikke overstige 100 downloads pr. kalenderdag). Dette ville dog helt gå glip af situationer, hvor en bruger foretager 99 downloads i løbet af timen før midnat og yderligere 99 i den første time af den nye dag.

Så hvis det krævede resultat mere er en "top ti downloaders liste", så er dette den anden tilgang. Resultaterne her er måske ikke så forståelige ved første øjekast, fordi en enkelt download kan tælle med flere intervaller. Dette skyldes, at intervallerne vil (og skal) overlappe.

Her er mit setup. Jeg har lavet tabellen ud fra din erklæring og tilføjet to indekser:

CREATE INDEX downloads_timestamp on downloads (dl_date);
CREATE INDEX downloads_user_id on downloads (user_id);
 

De data, jeg har indsat i tabellen:

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)
 

Som du kan se, fandt alle downloads sted enten i går eller i dag og blev udført af to forskellige brugere.

Nu, hvad vi skal huske på er følgende:Der er (matematisk) et uendeligt antal 24 timers intervaller (eller intervaller af enhver anden varighed) mellem '2011-01-24 0:00' og '2011-01-25 23 :59:59'. Men da serverens præcision er et sekund, koger dette ned til 86.400 intervaller:

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
 

Så vi kunne bruge en loop til at iterere over alle disse intervaller og beregne antallet af downloads pr. bruger og pr. interval. Det er selvfølgelig ikke alle intervaller, der har samme interesse for os, så vi kan springe nogle af dem over ved at bruge tidsstemplerne i tabellen som "begyndelse af intervallet".

Det er, hvad den følgende forespørgsel gør. Den bruger hvert downloadtidsstempel i tabellen som "start af interval", tilføjer intervallets varighed og forespørger derefter på antallet af downloads pr. bruger i løbet af dette interval.

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;
 

Her er resultatet:

+---------+---------------------+---------------------+-------+ | 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. Ekkolodsløber (ubuntu) udførelse mislykkedes:com.mysql.jdbc.Driver

  2. Vil du gemme PHP-array til MySQL?

  3. php kan ikke oprette forbindelse til mysql i docker-compose

  4. Valg af forskellige 2 kolonner kombination i mysql