sql >> データベース >  >> RDS >> Mysql

mysqlはタイムスパン間の行数を選択します

    OK、少し遅れていることに気づきましたが、とにかく答えを投稿したかったです:-)

    必要なことはサブクエリを使用して実行できますが、これは大きなテーブルで完了するのに時間がかかる場合があります...

    質問について考えると、2つの異なるアプローチにたどり着きました。

    それらの1つは、他の回答ですでに処理されています。特定の時点から開始し、この時点で開始する間隔を確認し、直後に続く等しい期間の間隔を確認することで機能します。これにより、明確で理解しやすい結果が得られ、おそらく必要となるでしょう(たとえば、ユーザーは1暦日あたり100ダウンロードを超えてはなりません)。ただし、これでは、ユーザーが深夜0時前の1時間に99回ダウンロードし、新しい日の最初の1時間にさらに99回ダウンロードするという状況を完全に見逃してしまいます。

    したがって、必要な結果が「トップ10ダウンローダーリスト」である場合、これは別のアプローチです。ここでの結果は、1回のダウンロードで複数の間隔にカウントされる可能性があるため、一見理解できない場合があります。これは、間隔が重なる(そして重なる必要がある)ためです。

    これが私の設定です。ステートメントからテーブルを作成し、2つのインデックスを追加しました:

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

    テーブルに挿入したデータ:

    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)
    

    ご覧のとおり、すべてのダウンロードは昨日または今日のいずれかで行われ、2人の異なるユーザーによって実行されました。

    ここで、注意しなければならないのは次のとおりです。「2011-01-240:00」と「2011-01-2523」の間には、(数学的に)24時間間隔(またはその他の期間の間隔)が無限にあります。 :59:59'。ただし、サーバーの精度は1秒であるため、これは86,400間隔になります。

    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
    

    したがって、ループを使用してこれらすべての間隔を反復処理し、ユーザーごとおよび間隔ごとのダウンロード数を計算できます。もちろん、すべての間隔が同じ関心事であるとは限らないため、表のタイムスタンプを「間隔の開始」として使用することで、一部の間隔をスキップできます。

    これは、次のクエリが行うことです。テーブル内のすべてのダウンロードタイムスタンプを「間隔の開始」として使用し、間隔の期間を追加してから、この間隔中のユーザーごとのダウンロード数を照会します。

    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;
    

    結果は次のとおりです。

    +---------+---------------------+---------------------+-------+
    | 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. 柔軟なコンテンツのためのデータベースへのXMLの保存

    2. どちらが速いですか:MySQL / PHPまたは静的ファイルから直接提供しますか?

    3. SQL ServerでRANK()を使用する方法

    4. Postgres:バキュームコマンドは死んだタプルをクリーンアップしません