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

MySQL GROUP BY cột và lấy bản ghi cập nhật gần nhất

Bài toán

Gom nhóm theo UserName + UserEmailId, nhưng chỉ giữ bản ghi có UserLastPost mới nhất (MAX).

Ví dụ

Tạo bảng:

CREATE TABLE DemoTable621 (
    UserName VARCHAR(100),
    UserEmailId VARCHAR(100),
    UserLastPost DATETIME
);
INSERT INTO DemoTable621 VALUES
('John', 'John@gmail.com', '2019-04-10 11:01:10'),
('John', 'John@gmail.com', '2019-07-14 13:07:10');

Truy vấn:

SELECT UserName, UserEmailId, MAX(UserLastPost)
FROM DemoTable621
GROUP BY UserName, UserEmailId;

Kết quả:

+----------+----------------+---------------------+
| UserName | UserEmailId    | max(UserLastPost)   |
+----------+----------------+---------------------+
| John     | John@gmail.com | 2019-07-14 13:07:10 |
+----------+----------------+---------------------+

Mở rộng: Lấy toàn bộ cột của dòng MAX (Greatest-N-Per-Group)

Nếu cần lấy cả cột khác của dòng có MAX date:

Cách 1: JOIN với subquery (MySQL tất cả version)

SELECT d1.*
FROM DemoTable621 d1
JOIN (
    SELECT UserName, UserEmailId, MAX(UserLastPost) AS max_post
    FROM DemoTable621
    GROUP BY UserName, UserEmailId
) d2 ON d1.UserName = d2.UserName
   AND d1.UserEmailId = d2.UserEmailId
   AND d1.UserLastPost = d2.max_post;

Cách 2: ROW_NUMBER() (MySQL 8.0+)

SELECT *
FROM (
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY UserName, UserEmailId ORDER BY UserLastPost DESC) AS rn
    FROM DemoTable621
) t
WHERE rn = 1;

Cách 3: Correlated subquery (chậm trên bảng lớn)

SELECT *
FROM DemoTable621 d1
WHERE UserLastPost = (
    SELECT MAX(UserLastPost)
    FROM DemoTable621 d2
    WHERE d2.UserName = d1.UserName
      AND d2.UserEmailId = d1.UserEmailId
);

Lưu ý

  • MySQL cho phép SELECT cột không trong GROUP BY (non-aggregated) nhưng giá trị không xác định (chỉ bật ONLY_FULL_GROUP_BY mới báo lỗi).
  • Luôn liệt kê rõ cột trong GROUP BY khớp với SELECT.
  • Index trên (UserName, UserEmailId, UserLastPost) tối ưu cho query này.