Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MySQL

MySQL: Gom dữ liệu theo giờ đăng nhập và lấy bản ghi gần nhất mỗi giờ

Sử dụng subquery với MAX(UNIX_TIMESTAMP()) gom theo HOUR(), sau đó JOIN ngược lại bảng gốc để lấy toàn bộ cột của bản ghi mới nhất mỗi giờ.

Cú pháp

SELECT b.* 
FROM (
    SELECT MAX(UNIX_TIMESTAMP(cot_thoi_gian)) AS max_ts
    FROM ten_bang
    GROUP BY HOUR(cot_thoi_gian)
) AS t_max
JOIN ten_bang b ON UNIX_TIMESTAMP(b.cot_thoi_gian) = t_max.max_ts
WHERE DATE(b.cot_thoi_gian) = 'ngay_can_loc';

Ví dụ minh họa

Tạo bảng log đăng nhập:

mysql> CREATE TABLE LayGioGanNhat (
    -> UserId INT,
    -> UserName VARCHAR(20),
    -> ThoiGianDangNhap DATETIME
    -> );

Chèn dữ liệu (ngày 2019-02-04, nhiều giờ):

mysql> INSERT INTO LayGioGanNhat VALUES 
    -> (100, 'John',  '2019-02-04 10:55:51'),
    -> (101, 'Larry', '2019-02-04 12:30:40'),
    -> (102, 'Carol', '2019-02-04 12:40:46'),
    -> (103, 'David', '2019-02-04 12:44:54'),
    -> (104, 'Bob',   '2019-02-04 12:47:59');

Truy vấn: Bản ghi đăng nhập muộn nhất mỗi giờ

mysql> SELECT tbl1.*
    -> FROM (
    ->   SELECT MAX(UNIX_TIMESTAMP(ThoiGianDangNhap)) AS m1
    ->   FROM LayGioGanNhat
    ->   GROUP BY HOUR(ThoiGianDangNhap)
    -> ) var1
    -> JOIN LayGioGanNhat tbl1 ON UNIX_TIMESTAMP(tbl1.ThoiGianDangNhap) = var1.m1
    -> WHERE DATE(tbl1.ThoiGianDangNhap) = '2019-02-04';

Kết quả (giờ 10: John, giờ 12: Bob - muộn nhất):

+--------+----------+---------------------+
| UserId | UserName | ThoiGianDangNhap    |
+--------+----------+---------------------+
| 100    | John     | 2019-02-04 10:55:51 |
| 104    | Bob      | 2019-02-04 12:47:59 |
+--------+----------+---------------------+

Cách hiện đại (MySQL 8.0+): Dùng Window Function ROW_NUMBER():

WITH ranked AS (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY HOUR(ThoiGianDangNhap) ORDER BY ThoiGianDangNhap DESC) AS rn
  FROM LayGioGanNhat
  WHERE DATE(ThoiGianDangNhap) = '2019-02-04'
)
SELECT * FROM ranked WHERE rn = 1;