首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Oracle 去重複不使用 DISTINCT:GROUP BY 進階技巧與效能對比

     編輯:Oracle 資料庫相關知識

DISTINCT 會觸發全量排序,大表效能差;且只能對「選取欄位全部相同」去重。若需「指定欄位去重並保留其他欄位」,GROUP BY 是正解。

核心模式

-- 以 A 為去重鍵,保留 B、C 的「首筆」值
SELECT A, MIN(B) AS B, MIN(C) AS C, COUNT(*) AS 重複次數
FROM   t
GROUP BY A
HAVING COUNT(*) >= 1;  -- =1 唯一值,>1 重複值

應用變體

需求HAVING 條件說明
只顯示重複資料COUNT(*) > 1找出髒資料
去重並保留第一筆COUNT(*) >= 1配合 MIN/MAX 取代表值
找出重複超過 N 次COUNT(*) > N嚴重重複排查

效能實測 (26 萬筆,僅品牌欄位有索引)

-- GROUP BY 版
SELECT brand, COUNT(*) FROM tab_commbaseinfo GROUP BY brand HAVING COUNT(*) = 1;
-- 平均 0.453 秒

-- DISTINCT 版
SELECT DISTINCT brand FROM tab_commbaseinfo;
-- 平均 0.39 秒

結論:單純去重 DISTINCT 略快;但 GROUP BY 提供聚合統計、保留其他欄位、條件過濾等 DISTINCT 無法做到的功能,綜合效能優於「DISTINCT + 子查詢」組合。

進階:ROW_NUMBER() 保留完整行 (10g+)

SELECT * FROM (
  SELECT t.*, ROW_NUMBER() OVER (PARTITION BY brand ORDER BY id) rn
  FROM tab_commbaseinfo t
) WHERE rn = 1;

此法可保留完整原始行 (非聚合值),且可指定保留邏輯 (最新/最舊/最大金額等)。

避坑指南

  • GROUP BY 欄位必須包含 SELECT 非聚合欄位,否則 ORA-00979。
  • HAVING 只能用於聚合條件,非聚合條件請放 WHERE。
  • 大表去重建議先建立去重鍵索引,或使用 CREATE TABLE new AS SELECT ... GROUP BY ... 避免排序溢位 TEMP。

根據業務需求選擇:單純去重用 DISTINCT,需統計/保留其他欄位用 GROUP BY,需保留完整行用 ROW_NUMBER()。

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