私にとって最も理にかなっていることと、質問がここと同じように提示された場合の回答方法に基づいて、そのようなアイデアを示します。
まず、データセット自体を想定し、テーブルに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回ログインしなかったユーザーをフィルタリングし、日付列を削除します。
ちょっと時間がかかりましたが、アイデアが溢れていると思いますし、面接で面白い答えが返ってくるのではないかと思います。 :)