sql >> Databáze >  >> RDS >> Mysql

mysql vyberte počet řádků mezi časovým rozpětím

Dobře, uvědomuji si, že jdu trochu pozdě, ale přesto jsem chtěl svou odpověď zveřejnit :-)

To, co požadujete, lze provést pomocí dílčího dotazu, ale dokončení na velkém stole může trvat věky...

Při přemýšlení o této otázce jsem dospěl ke dvěma různým přístupům.

Jedna z nich již byla řešena v ostatních odpovědích, funguje to tak, že se začíná v určitém časovém okamžiku, podívá se na interval, který začíná v tuto dobu, a pak se podívá na interval stejné délky, který bezprostředně následuje. To vede k jasným, srozumitelným výsledkům a je to pravděpodobně to, co by bylo požadováno (např. uživatel nesmí překročit 100 stažení za kalendářní den). To by však zcela vynechalo situace, kdy uživatel provede 99 stažení během hodiny před půlnocí a dalších 99 během první hodiny nového dne.

Pokud je tedy požadovaným výsledkem spíše „seznam deseti nejlepších stahovačů“, pak je to druhý přístup. Výsledky zde nemusí být na první pohled tak srozumitelné, protože jedno stažení se může počítat do více intervalů. Je to proto, že intervaly se budou (a musí) překrývat.

Tady je moje nastavení. Vytvořil jsem tabulku z vašeho příkazu a přidal jsem dva indexy:

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

Údaje, které jsem vložil do tabulky:

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 můžete vidět, všechna stahování proběhla včera nebo dnes a byla provedena dvěma různými uživateli.

Nyní si musíme uvědomit následující:Mezi '2011-01-24 0:00' a '2011-01-25 23 je (matematicky) nekonečný počet 24hodinových intervalů (nebo intervalů jakéhokoli jiného trvání). :59:59'. Ale protože přesnost serveru je jedna sekunda, sníží se to na 86 400 intervalů:

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

Mohli bychom tedy použít smyčku k iteraci přes všechny tyto intervaly a vypočítat počet stažení na uživatele a na interval. Samozřejmě, že ne všechny intervaly nás zajímají stejně, takže některé z nich můžeme přeskočit tím, že použijeme časová razítka v tabulce jako "začátek intervalu".

K tomu slouží následující dotaz. Použije každé časové razítko stahování v tabulce jako „začátek intervalu“, přidá trvání intervalu a poté se dotáže na počet stažení na uživatele během tohoto intervalu.

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;

Zde je výsledek:

+---------+---------------------+---------------------+-------+
| 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. Jak získat přístup k databázi Oracle přes síť?

  2. jak vložit více hodnot do jednoho pole v mysql

  3. Vyladění SQL Serveru – vše je o měření

  4. Stránkování s Oracle