Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Hitung pengguna aktif menggunakan stempel waktu masuk di MySQL

Saya akan menunjukkan ide seperti itu berdasarkan apa yang paling masuk akal bagi saya dan cara saya menjawab jika pertanyaannya sama seperti di sini:

Pertama, mari kita asumsikan kumpulan data seperti itu, kita akan memberi nama tabel 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 |
|   ...   |          ...        |
+---------+---------------------+

Mungkin ada kolom lain, tapi kami tidak mempermasalahkannya.

Pertama-tama kita harus menentukan batas minggu itu, untuk itu kita bisa menggunakan ADDDATE() . Dikombinasikan dengan gagasan bahwa tanggal hari ini-hari ini adalah hari kerja (DAYOFWEEK() MySQL ), adalah tanggal minggu.

Misalnya:Jika hari ini Rabu tanggal 10, Wed - 3 = Sun , jadi 10 - 3 = 7 , dan kita dapat mengharapkan hari Minggu menjadi tanggal 7.

Kita bisa mendapatkan WeekStart dan WeekEnd stempel waktu seperti ini:

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;

Catatan:di PostgreSQL ada DATE_TRUNC() fungsi yang mengembalikan awal unit waktu tertentu, diberi tanggal, seperti awal minggu, bulan, jam, dan sebagainya. Tapi itu tidak tersedia di MySQL.

Selanjutnya, mari kita gunakan WeekStart dan WeekEnd untuk mengeklik kumpulan data kita, dalam contoh ini saya hanya akan menunjukkan cara memfilter, menggunakan tanggal kode keras:

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

Ini akan mengembalikan kumpulan data kami yang terpotong, dengan hanya hasil yang relevan:

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

Kami kemudian dapat mengurangi set hasil kami menjadi hanya user_id s, dan menyaring duplikat. lalu hitung, begini:

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 akan menyaring duplikat, dan count hanya akan mengembalikan jumlahnya.

Jika digabungkan menjadi:

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")

Ganti CURDATE() dengan stempel waktu apa pun untuk mendapatkan jumlah login pengguna minggu itu.

Tapi saya perlu memecah ini menjadi beberapa hari, saya mendengar Anda menangis. Tentu saja! dan begini caranya:

Pertama, mari kita terjemahkan stempel waktu kita yang terlalu informatif menjadi hanya data tanggal. Kami menambahkan DISTINCT karena kami tidak keberatan pengguna yang sama masuk dua kali pada hari yang sama. kami menghitung pengguna, bukan login, bukan? (perhatikan kita mundur ke sini):

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

Ini menghasilkan:

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

Kueri ini, akan kami bungkus dengan satu detik, untuk menghitung kemunculan setiap tanggal:

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`

Kami menggunakan hitungan dan pengelompokan untuk mendapatkan daftar berdasarkan tanggal, yang mengembalikan:

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

Dan setelah semua kerja keras, keduanya digabungkan:

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`;

Akan memberi Anda rincian login harian per hari dalam minggu ini. Sekali lagi, ganti CURDATE() untuk mendapatkan minggu yang berbeda.

Adapun pengguna sendiri yang masuk, mari gabungkan hal yang sama dalam urutan yang berbeda:

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

Saya memiliki dua pertanyaan dalam, yang pertama adalah logins :

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

Akan memberikan daftar pengguna, dan hari-hari ketika mereka masuk, tanpa duplikat.

Kemudian kita memiliki logincounts :

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

Akan mengembalikan daftar yang sama, dengan hitungan berapa banyak login yang dimiliki setiap pengguna.

Dan terakhir:PILIH user_id DARI logincounts -- Lihat subquery sebelumnya.WHERE login_count> 6

Filter kami yang tidak login 7 kali, dan hapus kolom tanggal.

Ini agak panjang, tapi saya pikir ini penuh dengan ide dan saya pikir itu pasti membantu menjawab dengan cara yang menarik dalam wawancara kerja. :)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Pilih postingan yang tidak memiliki tag tertentu

  2. Klien koneksi Mariadb:Akses ditolak untuk pengguna (menggunakan kata sandi:TIDAK) di mysql 8.0

  3. Merujuk ke nilai array asosiatif dari PDO::FETCH_ASSOC

  4. Gunakan Java untuk mencadangkan database MySQL dari jarak jauh

  5. Bisakah kita membatasi jumlah baris dalam tabel di MySQL?