首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL 取得每群組第一筆資料:SQL Server、Oracle、MySQL 三大平台寫法對照

     編輯:關於SqlServer

場景

日誌表 Log(Grp, CreateTime, ...),每群組 (Grp) 依時間倒序取最新一筆。

SQL Server 寫法

相關子查詢 (通用、舊版相容)

SELECT * 
FROM Log T
WHERE Id = (
  SELECT TOP 1 Id 
  FROM Log 
  WHERE Grp = T.Grp 
  ORDER BY CreateTime DESC
);

ROW_NUMBER() 視窗函數 (SQL 2005+,推薦)

WITH Ranked AS (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY Grp ORDER BY CreateTime DESC) AS Rn
  FROM Log
)
SELECT * FROM Ranked WHERE Rn = 1;

TOP 1 WITH TIES + ORDER BY (技巧寫法)

SELECT TOP 1 WITH TIES * 
FROM Log 
ORDER BY ROW_NUMBER() OVER (PARTITION BY Grp ORDER BY CreateTime DESC);

Oracle 寫法

分析函數 ROW_NUMBER (標準)

SELECT * FROM (
  SELECT 
    Type, Code,
    ROW_NUMBER() OVER (PARTITION BY Type ORDER BY Code) AS Rn
  FROM Group_Info
) WHERE Rn = 1;

聚合函數 MIN/MAX (僅需鍵值)

SELECT Type, MIN(Code) FROM Group_Info GROUP BY Type;

注意:SELECT 清單非聚合欄位必須在 GROUP BY 或包裹聚合函數,否則 ORA-00979。

MySQL 寫法

LIMIT 分頁 (單群組)

SELECT * FROM Log ORDER BY CreateTime DESC LIMIT 0, 1;

每群組第一筆 (MySQL 8.0+ 視窗函數)

WITH Ranked AS (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY Grp ORDER BY CreateTime DESC) AS Rn
  FROM Log
)
SELECT * FROM Ranked WHERE Rn = 1;

MySQL 5.7 變數模擬 (不推薦生產)

SELECT Grp, CreateTime, Data FROM (
  SELECT 
    Grp, CreateTime, Data,
    @rn := IF(@prev = Grp, @rn + 1, 1) AS Rn,
    @prev := Grp
  FROM Log
  CROSS JOIN (SELECT @rn := 0, @prev := NULL) vars
  ORDER BY Grp, CreateTime DESC
) T WHERE Rn = 1;

跨平台對照表

平台標準視窗函數舊版替代備註
SQL ServerROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) (2005+)相關子查詢 TOP 1CTE 寫法最清晰
OracleROW_NUMBER() OVER (...) (8i+)MIN/MAX 聚合 (僅鍵值)分析函數成熟
PostgreSQLROW_NUMBER() OVER (...) (8.4+)DISTINCT ON (Grp) ORDER BY Grp, CreateTime DESCDISTINCT ON 為 PG 獨有簡潔語法
MySQLROW_NUMBER() OVER (...) (8.0+)用戶變數模擬5.7 升級 8.0 即可用標準寫法

效能提示

  • 分區欄位 (Grp) + 排序欄位 (CreateTime) 建立複合索引 (Grp, CreateTime DESC)。
  • 視窗函數通常優於相關子查詢 (單掃描 vs 多次查找)。
  • 大資料量考慮分頁/流式處理,避免一次性物化全量排序結果。

結語

ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) 是 ANSI SQL 標準、跨平台通用的「每群組 Top-N」解法。SQL Server 2005+、Oracle 8i+、PostgreSQL 8.4+、MySQL 8.0+ 均完整支援。舊版平台以相關子查詢或廠商特有語法 (DISTINCT ON) 替代。統一採用標準視窗函數,提升可移植性與可維護性。

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