萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

SQL 分組取每組最大值記錄:GROUP BY + 子查詢 / JOIN 實戰寫法

核心問題

需求:依欄位 aid 分組,取每組 day 最大值對應的完整記錄。

標準解法:子查詢 + 回表

SELECT A.*
FROM test A
JOIN (
    SELECT aid, MAX(day) AS max_day
    FROM test
    GROUP BY aid
) B ON A.aid = B.aid AND A.day = B.max_day
ORDER BY A.install DESC;

原理:衍生表 B 只含各組最大 day,再 JOIN 回主表取完整欄位。

替代寫法:WHERE IN 子查詢

SELECT * FROM test
WHERE (aid, day) IN (
    SELECT aid, MAX(day) FROM test GROUP BY aid
);

MySQL 5.7+ 支援多欄 IN 子查詢,語意清晰。

MSSQL / 通用寫法:相關子查詢

SELECT * FROM table1 a
WHERE b = (SELECT MAX(b) FROM table1 WHERE a = a.a);

或使用 ROW_NUMBER() 窗口函數(MySQL 8.0+、PostgreSQL、SQL Server、Oracle):

WITH ranked AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY aid ORDER BY day DESC) AS rn
    FROM test
)
SELECT * FROM ranked WHERE rn = 1;

效能比較建議

  • 小資料量:JOIN 與 IN 差異不大。
  • 大資料量:確保 (aid, day) 有複合索引,JOIN 通常優於相關子查詢。
  • MySQL 8.0+:優先用 ROW_NUMBER(),可讀性與效能俱佳。

範例資料驗證

CREATE TABLE test (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  install VARCHAR(50),
  day INT UNSIGNED,
  aid INT UNSIGNED
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO test (install, day, aid) VALUES
('www.111cn.net', 20120308, 1),
(2321, 20120309, 2),
(1236, 20120310, 3),
('www.111cn.net', 20120309, 1),
(2312, 20120310, 1),
(1432, 20120311, 1),
(2421, 20120308, 2),
(4245, 20120311, 2),
('www.111cn.net', 20120310, 2),
(412, 20120308, 3);

執行上述查詢,將得到每組 aid 最新 day 的完整列。

copyright © 萬盛學電腦網 all rights reserved