首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Oracle 去重並保留創建時間最早記錄:ROW_NUMBER() 開窗函數最佳實踐

     編輯:程式設計綜合問答

場景

表結構:`id` (PK)、`phone`、`create_time`。需按 `phone` 去重,**保留每組 `create_time` 最早的一條完整記錄**(含 id、phone、create_time)。

標準解法:`ROW_NUMBER()` 分組排序

SELECT id, phone, create_time
FROM (
    SELECT 
        id, 
        phone, 
        create_time,
        ROW_NUMBER() OVER (PARTITION BY phone ORDER BY create_time ASC) AS rn
    FROM your_table
) t
WHERE rn = 1;

關鍵點解析

  • `PARTITION BY phone`:按手機號分組。
  • `ORDER BY create_time ASC`:組內按創建時間升序,**最早的排第一**。
  • `ROW_NUMBER()`:為組內每行分配唯一遞增序號 (1,2,3...)。
  • 外層 `WHERE rn = 1`:只取每組第一行 → **最早記錄**。

替代方案對比

方案語法性能適用版本備註
ROW_NUMBER (推薦)標準 SQL:2003優,單掃描Oracle 10g+最通用、可移植
KEEP (DENSE_RANK FIRST)Oracle 專有優Oracle 9i+只能取聚合值,難取完整行
子查詢 + MIN(create_time)傳統 SQL差,多次掃描/連接所有版本需再 JOIN 回表取 id
RANK / DENSE_RANK標準 SQL同 ROW_NUMBEROracle 10g+若時間相同會產生多行 rn=1

若需「最晚記錄」

ROW_NUMBER() OVER (PARTITION BY phone ORDER BY create_time DESC) -- 降序

性能優化建議

  1. **索引**:`CREATE INDEX idx_phone_time ON your_table(phone, create_time);` 覆蓋分組排序列。
  2. **分區表**:若數據量極大 (億級),按 `phone` 哈希分區 + 本地索引。
  3. **並行查詢**:`SELECT /*+ PARALLEL(4) */ ...` 利用多 CPU。

原回答補充

原最佳回答給出 `ROW_NUMBER()` 核心代碼並附參考鏈接,上文補充完整語法解析、替代方案對比表、索引優化建議、最晚記錄寫法,更適合直接落地。

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