sql >> Database >  >> RDS >> Mysql

mysql selecteer aantal rijen tussen tijdspanne

OK, ik besef dat ik een beetje laat ben, maar ik wilde mijn antwoord toch posten :-)

Wat je nodig hebt, kan worden gedaan met behulp van een subquery, maar dit kan eeuwen duren om te voltooien op een grote tafel...

Nadenkend over de vraag kwam ik tot twee verschillende benaderingen.

Een daarvan is al behandeld in de andere antwoorden, het werkt door op een bepaald tijdstip te beginnen, te kijken naar het interval dat op dit moment begint en vervolgens te kijken naar het interval van gelijke duur dat onmiddellijk volgt. Dit leidt tot duidelijke, begrijpelijke resultaten en is waarschijnlijk ook vereist (de gebruiker mag bijvoorbeeld niet meer dan 100 downloads per kalenderdag hebben). Dit zou echter volledig voorbijgaan aan situaties waarin een gebruiker 99 downloads doet in het uur voor middernacht en nog eens 99 in het eerste uur van de nieuwe dag.

Dus als het vereiste resultaat meer een "top tien downloaderslijst" is, dan is dit de andere benadering. De resultaten hier zijn op het eerste gezicht misschien niet zo begrijpelijk, omdat één enkele download kan meetellen voor meerdere intervallen. Dit komt omdat de intervallen elkaar zullen (en moeten) overlappen.

Hier is mijn opstelling. Ik heb de tabel gemaakt op basis van uw verklaring en twee indexen toegevoegd:

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

De gegevens die ik in de tabel heb ingevoegd:

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)

Zoals u kunt zien, vonden alle downloads gisteren of vandaag plaats en werden uitgevoerd door twee verschillende gebruikers.

Nu moeten we op het volgende letten:Er is (wiskundig) een oneindig aantal intervallen van 24 uur (of intervallen van een andere duur) tussen '2011-01-24 0:00' en '2011-01-25 23 :59:59'. Maar aangezien de precisie van de server één seconde is, komt dit neer op 86.400 intervallen:

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

We zouden dus een lus kunnen gebruiken om al deze intervallen te herhalen en het aantal downloads per gebruiker en per interval te berekenen. Natuurlijk zijn niet alle intervallen voor ons even interessant, dus we kunnen er enkele overslaan door de tijdstempels in de tabel te gebruiken als "begin van interval".

Dit is wat de volgende query doet. Het gebruikt elke downloadtijdstempel in de tabel als "begin van interval", voegt de intervalduur toe en vraagt ​​vervolgens het aantal downloads per gebruiker tijdens dit interval op.

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;

Dit is het resultaat:

+---------+---------------------+---------------------+-------+
| 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. Statistische gegevens opslaan, heb ik DECIMAL, FLOAT of DOUBLE nodig?

  2. Installatie van pg gem mislukt, mkmf.rb kan geen header-bestanden voor ruby ​​vinden (Mac OSX 10.6.5)

  3. MySQL-query:alle items ouder dan 1 jaar opvragen

  4. Hoe maak je een dynamische matrix in php?