首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 取得每個 userid 最新一筆記錄:GROUP_CONCAT + SUBSTRING_INDEX 技巧

     編輯:MySQL 資料庫相關知識

表 t1 無主鍵,userid 重複,需取每個 userid 時間最近(atime 最大)的一筆。常規做法需臨時表或 JOIN,這裡介紹單一查詢技巧:GROUP_CONCAT + SUBSTRING_INDEX。

測試資料

CREATE TABLE `t1` (
  `userid` int(11) DEFAULT NULL,
  `atime` datetime DEFAULT NULL,
  KEY `idx_userid` (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO t1 VALUES
(1, '2013-08-12 11:05:25'), (2, '2013-08-12 11:05:29'),
(3, '2013-08-12 11:05:32'), (5, '2013-08-12 11:05:34'),
(1, '2013-08-12 11:05:40'), (2, '2013-08-12 11:05:43'),
(3, '2013-08-12 11:05:48'), (5, '2013-08-12 11:06:03');

單一查詢解法

SELECT userid,
       SUBSTRING_INDEX(GROUP_CONCAT(atime ORDER BY atime DESC), ',', 1) AS atime
FROM t1
GROUP BY userid;

執行結果

+--------+---------------------+
| userid | atime               |
+--------+---------------------+
| 1      | 2013-08-12 11:05:40 |
| 2      | 2013-08-12 11:05:43 |
| 3      | 2013-08-12 11:05:48 |
| 5      | 2013-08-12 11:06:03 |
+--------+---------------------+

原理解析

  1. GROUP_CONCAT(atime ORDER BY atime DESC):各群組內將時間按降序串聯成字串,如 '2013-08-12 11:05:40,2013-08-12 11:05:25'。
  2. SUBSTRING_INDEX(..., ',', 1):取第一個逗號前的子串,即最大時間值。

注意事項與替代方案

  • group_concat_max_len 預設 1024 字節,群組成員極多時會截斷。可臨時調大:SET SESSION group_concat_max_len = 1000000;。
  • MySQL 8.0+ 建議使用視窗函式:ROW_NUMBER() OVER (PARTITION BY userid ORDER BY atime DESC),語義更清晰、效能更穩定。
  • 若需取得整列(含其他欄位),可用子查詢 JOIN 或 MAX(atime) 關聯回原表。

此技巧適用於快速分析、資料量中等、不想建立臨時表的場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved