需求:文章表 Article(Id, Category, InsertDate),查詢每個分類下最新的 N 篇文章。本文提供經典自連接計數法與 MySQL 8.0 窗口函數法兩種方案。
SELECT A1.*
FROM Article AS A1
INNER JOIN (
SELECT A.Category, A.InsertDate
FROM Article AS A
LEFT JOIN Article AS B
ON A.Category = B.Category
AND A.InsertDate <= B.InsertDate
GROUP BY A.Category, A.InsertDate
HAVING COUNT(B.InsertDate) <= @N
) AS B1
ON A1.Category = B1.Category
AND A1.InsertDate = B1.InsertDate
ORDER BY A1.Category, A1.InsertDate DESC;
原理:對同分類中日期 >= 當前行的行數計數,若 ≤ N 則為 Top-N。@N 為參數。
WITH ranked AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY Category ORDER BY InsertDate DESC) AS rn
FROM Article
)
SELECT Id, Category, InsertDate
FROM ranked
WHERE rn <= 3; -- 取前 3
優點:語法清晰、效能優於自連接(避免 O(N²) 計數)、易擴展(如 RANK()、DENSE_RANK() 處理並列)。
SELECT A1.*
FROM prcKx AS A1
INNER JOIN (
SELECT A.superId, A.prcid
FROM prcKx AS A
LEFT JOIN prcKx AS B
ON A.superId = B.superId
AND A.prcid <= B.prcid
GROUP BY A.superId, A.prcid
HAVING COUNT(B.prcid) <= 7
) AS B1
ON A1.superId = B1.superId
AND A1.prcid = B1.prcid
ORDER BY A1.superId, A1.prcid;
(Category, InsertDate) 建立復合索引。(Category, InsertDate DESC) 索引。