sql >> Databasteknik >  >> RDS >> Mysql

mysql välj antal rader mellan tidsintervall

OK, jag inser att jag är lite sen, men jag ville skicka mitt svar ändå :-)

Det du behöver kan göras med hjälp av en underfråga, men det kan ta evigheter att slutföra på ett stort bord...

När jag funderade på frågan kom jag till två olika tillvägagångssätt.

En av dem har redan behandlats i de andra svaren, den fungerar genom att man börjar vid en specifik tidpunkt, tittar på intervallet som börjar vid denna tidpunkt och tittar sedan på intervallet med lika lång varaktighet som omedelbart följer. Detta leder till tydliga, begripliga resultat och är förmodligen vad som skulle krävas (t.ex. får användaren inte överstiga 100 nedladdningar per kalenderdag). Detta skulle dock helt missa situationer där en användare gör 99 nedladdningar under timmen före midnatt och ytterligare 99 under den första timmen av den nya dagen.

Så om det önskade resultatet är mer av en "topp tio nedladdningslista", så är detta det andra tillvägagångssättet. Resultaten här kanske inte är lika förståeliga vid första anblicken, eftersom en enda nedladdning kan räknas till flera intervall. Detta beror på att intervallen kommer (och måste) överlappa varandra.

Här är min inställning. Jag har skapat tabellen från ditt uttalande och lagt till två index:

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

Datan jag har infogat 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 skedde alla nedladdningar antingen igår eller idag och utfördes av två olika användare.

Vad vi nu måste tänka på är följande:Det finns (matematiskt) ett oändligt antal 24-timmarsintervall (eller intervall av någon annan varaktighet) mellan '2011-01-24 0:00' och '2011-01-25 23 :59:59'. Men eftersom serverns precision är en sekund, kokar detta ner till 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 kunde använda en loop för att iterera över alla dessa intervall och beräkna antalet nedladdningar per användare och per intervall. Naturligtvis är inte alla intervall av samma intresse för oss, så vi kan hoppa över några av dem genom att använda tidsstämplarna i tabellen som "intervallets början".

Detta är vad följande fråga gör. Den använder varje nedladdningstidstämpel i tabellen som "start av intervall", lägger till intervallets varaktighet och frågar sedan antalet nedladdningar per användare under detta intervall.

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;

Här är 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. MySQL sök json värde med nyckel i array

  2. Apache NiFi

  3. REGEXP-prestanda (jämför med LIKE och =)

  4. Följ geospatial fråga:hitta n närmaste punkter till en plats