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

MySQLのログインタイムスタンプを使用してアクティブユーザーをカウントします

    私にとって最も理にかなっていることと、質問がここと同じように提示された場合の回答方法に基づいて、そのようなアイデアを示します。

    まず、データセット自体を想定し、テーブルにloginsという名前を付けます。 :

    +---------+---------------------+
    | user_id |   login_timestamp   |
    +---------+---------------------+
    |       1 | 2015-09-29 14:05:05 |
    |       2 | 2015-09-29 14:05:08 |
    |       1 | 2015-09-29 14:05:12 |
    |       4 | 2015-09-22 14:05:18 |
    |   ...   |          ...        |
    +---------+---------------------+
    

    他の列があるかもしれませんが、私たちはそれらを気にしません。

    まず、その週の境界線を決定する必要があります。そのために、ADDDATE()を使用できます。 。今日の日付-今日の平日(MySQLのDAYOFWEEK() )、日曜日の日付です。

    例:今日が10日の水曜日の場合、Wed - 3 = Sun 、したがって、10 - 3 = 7 、そして日曜日は7日になると期待できます。

    WeekStartを取得できます およびWeekEnd この方法のタイムスタンプ:

    SELECT
    DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 1-DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 00:00:00") WeekStart, 
    DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 7-DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 23:59:59") WeekEnd;
    

    注:PostgreSQLにはDATE_TRUNC()があります 週の開始、月、時間などの日付を指定して、指定された時間単位の開始を返す関数。しかし、それはMySQLでは利用できません。

    次に、データセットを連結するためにWeekStartとweekEndを利用しましょう。この例では、ハードコードされた日付を使用してフィルタリングする方法を示します。

    SELECT *
    FROM `logins`
    WHERE login_timestamp BETWEEN '2015-09-29 14:05:07' AND '2015-09-29 14:05:13'
    

    これにより、スライスされたデータセットが返され、関連する結果のみが返されます。

    +---------+---------------------+
    | user_id |   login_timestamp   |
    +---------+---------------------+
    |       2 | 2015-09-29 14:05:08 |
    |       1 | 2015-09-29 14:05:12 |
    +---------+---------------------+
    

    次に、結果セットをuser_idのみに減らすことができます。 s、および重複を除外します。次に、このように数えます:

    SELECT COUNT(DISTINCT user_id)
    FROM `logins`
    WHERE login_timestamp BETWEEN '2015-09-29 14:05:07' AND '2015-09-29 14:05:13'
    

    DISTINCT 重複を除外し、カウントは金額だけを返します。

    組み合わせると、これは次のようになります。

    SELECT COUNT(DISTINCT user_id)
    FROM `logins`
    WHERE login_timestamp 
        BETWEEN DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 1- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 00:00:00") 
            AND DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 7- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 23:59:59")
    

    CURDATE()を置き換えます その週のユーザーログイン数を取得するために、任意のタイムスタンプを使用します。

    しかし、私はこれを数日に分解する必要があります、私はあなたが泣くのを聞きます。もちろん!方法は次のとおりです。

    まず、情報量の多いタイムスタンプを日付データのみに変換しましょう。 DISTINCTを追加します 同じユーザーが同じ日に2回ログインしてもかまわないからです。ログインではなくユーザーをカウントしますよね? (ここに戻ることに注意してください):

    SELECT DISTINCT user_id, DATE_FORMAT(login_timestamp, "%Y-%m-%d")
    FROM `logins`
    

    これにより、次のようになります。

    +---------+-----------------+
    | user_id | login_timestamp |
    +---------+-----------------+
    |       1 | 2015-09-29      |
    |       2 | 2015-09-29      |
    |       4 | 2015-09-22      |
    |   ...   |        ...      |
    +---------+-----------------+
    

    このクエリでは、すべての日付の出現をカウントするために、1秒でラップします:

    SELECT `login_timestamp`, count(*) AS 'count'
    FROM (SELECT DISTINCT user_id, DATE_FORMAT(login_timestamp, "%Y-%m-%d") AS `login_timestamp` FROM `logins`) `loginsMod`
    GROUP BY `login_timestamp`
    

    日付でリストを取得するために、カウントとグループ化を使用します。これにより、次の結果が返されます。

    +-----------------+-------+
    | login_timestamp | count |
    +-----------------+-------+
    | 2015-09-29      | 1     +
    | 2015-09-22      | 2     +
    +-----------------+-------+
    

    そして、すべてのハードワークの後、両方が組み合わされました:

    SELECT `login_timestamp`, COUNT(*)
    FROM (
    SELECT DISTINCT user_id, DATE_FORMAT(login_timestamp, "%Y-%m-%d") AS `login_timestamp`
    FROM `logins`
    WHERE login_timestamp BETWEEN DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 1- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 00:00:00") AND DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 7- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 23:59:59")) `loginsMod`
    GROUP BY `login_timestamp`;
    

    今週の1日あたりのログインの毎日の内訳を示します。繰り返しますが、CURDATE()を置き換えます 別の週を取得します。

    ログインしたユーザー自身については、同じものを別の順序で組み合わせてみましょう。

    SELECT `user_id`
    FROM (
        SELECT `user_id`, COUNT(*) AS `login_count`
        FROM (
            SELECT DISTINCT `user_id`, DATE_FORMAT(`login_timestamp`, "%Y-%m-%d")
            FROM `logins`) `logins`
        GROUP BY `user_id`) `logincounts`
    WHERE `login_count` > 6
    

    2つの内部クエリがあります。1つ目はloginsです。 :

    SELECT DISTINCT `user_id`, DATE_FORMAT(`login_timestamp`, "%Y-%m-%d")
    FROM `logins`
    

    ユーザーのリストと、ユーザーがログオンした日を重複せずに提供します。

    次に、logincounts

    SELECT `user_id`, COUNT(*) AS `login_count`
    FROM `logins` -- See previous subquery.
    GROUP BY `user_id`) `logincounts`
    

    各ユーザーのログイン数をカウントした同じリストが返されます。

    そして最後に:SELECT user_id FROM logincounts -前のサブクエリを参照してください。login_count> 6

    7回ログインしなかったユーザーをフィルタリングし、日付列を削除します。

    ちょっと時間がかかりましたが、アイデアが溢れていると思いますし、面接で面白い答えが返ってくるのではないかと思います。 :)



    1. 大きなCSVファイルをMysqlデータベースにアップロードする

    2. PostgreSQLの2つの列から最初のnull以外のセルを選択します

    3. JSONサブコンポーネントを抽出するための演算子

    4. PHPでSQLクエリの実行を停止するにはどうすればよいですか?