Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Đếm số người dùng đang hoạt động bằng cách sử dụng dấu thời gian đăng nhập trong MySQL

Tôi sẽ chứng minh một ý tưởng như vậy dựa trên những gì có ý nghĩa nhất đối với tôi và cách tôi sẽ trả lời nếu câu hỏi được trình bày giống như ở đây:

Trước tiên, hãy giả sử một tập dữ liệu như vậy, chúng tôi sẽ đặt tên cho bảng là 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 |
|   ...   |          ...        |
+---------+---------------------+

Có thể có các cột khác, nhưng chúng tôi không bận tâm đến những cột đó.

Trước hết, chúng ta nên xác định biên giới của tuần đó, chúng ta có thể sử dụng ADDDATE() . Kết hợp với ý tưởng rằng ngày hôm nay-ngày hôm nay trong tuần (DAYOFWEEK() của MySQL ), là ngày chủ nhật.

Ví dụ:Nếu hôm nay là Thứ Tư ngày 10, Wed - 3 = Sun , do đó 10 - 3 = 7 và chúng ta có thể mong đợi Chủ nhật là ngày thứ 7.

Chúng ta có thể nhận được WeekStartWeekEnd dấu thời gian theo cách này:

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;

Lưu ý:trong PostgreSQL có DATE_TRUNC() hàm trả về đầu của một đơn vị thời gian cụ thể, một ngày cụ thể, chẳng hạn như bắt đầu tuần, tháng, giờ, v.v. Nhưng điều đó không có sẵn trong MySQL.

Tiếp theo, hãy sử dụng WeekStart và weekEnd để cắt bớt tập dữ liệu của chúng tôi, trong ví dụ này, tôi sẽ chỉ trình bày cách lọc, sử dụng các ngày được mã hóa cứng:

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

Điều này sẽ trả về tập dữ liệu của chúng tôi được cắt lát, chỉ với các kết quả có liên quan:

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

Sau đó, chúng tôi có thể giảm tập hợp kết quả của mình thành chỉ user_id s, và lọc ra các bản sao. sau đó đếm, theo cách này:

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 sẽ lọc ra các bản sao và đếm sẽ chỉ trả về số tiền.

Kết hợp lại, điều này trở thành:

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

Thay thế CURDATE() với bất kỳ dấu thời gian nào để có được số lượt đăng nhập của người dùng trong tuần đó.

Nhưng tôi cần phải phá vỡ điều này cho đến ngày, tôi nghe thấy bạn khóc. Tất nhiên! và đây là cách:

Trước tiên, hãy dịch dấu thời gian quá nhiều thông tin của chúng tôi sang chỉ dữ liệu ngày. Chúng tôi thêm DISTINCT bởi vì chúng tôi không phiền khi cùng một người dùng đăng nhập hai lần trong cùng một ngày. chúng tôi tính người dùng, không phải đăng nhập, phải không? (lưu ý chúng tôi lùi lại đây):

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

Điều này mang lại:

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

Truy vấn này, chúng tôi sẽ kết thúc bằng một giây, để đếm số lần xuất hiện của mọi ngày:

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`

Chúng tôi sử dụng số lượng và một nhóm để lấy danh sách theo ngày, trả về:

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

Và sau tất cả những công việc khó khăn, cả hai đã kết hợp lại:

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

Sẽ cung cấp cho bạn bảng phân tích hàng ngày về thông tin đăng nhập mỗi ngày trong tuần này. Một lần nữa, thay thế CURDATE() để có một tuần khác.

Đối với chính những người dùng đã đăng nhập, hãy kết hợp những thứ giống nhau theo một thứ tự khác nhau:

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

Tôi có hai truy vấn bên trong, truy vấn đầu tiên là logins :

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

Sẽ cung cấp danh sách người dùng và ngày họ đăng nhập, không trùng lặp.

Sau đó, chúng tôi có logincounts :

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

Sẽ trả về cùng một danh sách, với số lượng đăng nhập mà mỗi người dùng đã có.

Và cuối cùng:CHỌN user_id TỪ logincounts - Xem truy vấn con trước đó. WHERE login_count> 6

Lọc những người không đăng nhập của chúng tôi 7 lần và bỏ cột ngày.

Điều này hơi dài, nhưng tôi nghĩ nó có rất nhiều ý tưởng và tôi nghĩ nó chắc chắn có thể giúp trả lời một cách thú vị trong một cuộc phỏng vấn làm việc. :)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tham chiếu không xác định Cpp-Mysql đến lỗi 'một hàm'

  2. MySQL GROUP BY hành vi

  3. Lumen 5.6 Lỗi di chuyển Khóa được chỉ định quá dài Độ dài khóa tối đa là 767 byte

  4. Chỉ các biến nên được chuyển bằng tham chiếu trong ... trên dòng 13 Không thành công

  5. MYSQL &Phpmyadmin không hiển thị cùng một DB