表 t1(uid INT, atime DATETIME, KEY idx_uid(uid)),uid 重複,需取每個 uid 對應 最大 atime 的那一行。
-- 1. 衍生表 JOIN
SELECT t1.* FROM t1
JOIN (SELECT uid, MAX(atime) AS max_at FROM t1 GROUP BY uid) t2
ON t1.uid=t2.uid AND t1.atime=t2.max_at;
-- 2. 相關子查詢
SELECT * FROM t1 t
WHERE atime = (SELECT MAX(atime) FROM t1 WHERE uid=t.uid);
-- 3. MySQL 8.0+ 窗口函數
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY uid ORDER BY atime DESC) AS rn
FROM t1
) t WHERE rn=1;
SELECT uid,
SUBSTRING_INDEX(GROUP_CONCAT(atime ORDER BY atime DESC), ',', 1) AS latest_atime
FROM t1
GROUP BY uid;
GROUP_CONCAT(atime ORDER BY atime DESC):組內按時間倒序拼接成 '2013-08-12 11:05:40,2013-08-12 11:05:25'。SUBSTRING_INDEX(..., ',', 1):取第一個逗號前的子串,即最大時間。+--------+---------------------+
| uid | latest_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 |
+--------+---------------------+
| 限制 | 影響 | 應對 |
|---|---|---|
group_concat_max_len 默認 1024 字節 | 組內行數極多時被截斷,導致取值錯誤 | SET SESSION group_concat_max_len = 1000000; |
| 若需取「整行」而非單列 | 需將多列拼接為單字符串再拆解,極其脆弱 | 改用 JOIN/窗口函數,穩健可維護 |
| 含 NULL 值 | GROUP_CONCAT 忽略 NULL,可能導致順序錯位 | 業務保證非 NULL 或用 COALESCE 佔位 |