1. 程式人生 > >Oracle 根據某個欄位對查詢結果去重 三種方法詳述

Oracle 根據某個欄位對查詢結果去重 三種方法詳述

Oracle三種去重的方法

  • distinct
  • group by
  • rowid

分組函式:作用於一組資料,並對一組資料返回一個值

常見的分組函式有:
count 返回找到的記錄數
min 返回一個數字列或計算列的最小值
max 返回一個數字列或計算列的最大值
sum 返回一個數字列或計算列總和
avg 返回一個數字列或計算列的平均值

一、distinct

distinct 單列

select distinct(a) from tableA;

distinct 多列

--會報錯,distinct 必須放在 select 語句的最前方
select a, distinct b,c from tableA;
select distinct a,b,c from tableA;

多列的時候,上述語句是針對abc的組合來distinct的,列出的是abc的所有不同組合,相當於下列語句

select a,b,c from tableA group by a,b,c;

那麼,如果想要分別查詢a,b,c三個欄位的distinct值怎麼辦?一開始可能只想到下列三個語句

select distinct a from tableA;
select distinct b from tableA;
select distinct
c from tableA;

麻煩,如何合併成一個語句呢,使用union解決,後面拼接的字串是為了標識這個值屬於哪個欄位:

select distinct(a) || ' a' from tableA
union all
select distinct(b) || ' b' from tableA
union all
select distinct(c) || ' c' from tableA

二、group by

只查詢非分組函式,不需要使用group by

select Name, Gender from dba_data_files;

只要查詢了分組函式,就需要使用group by

  1. 只查詢分組函式的話,group by的子句裡用到的列名Name 和 Gender,不需要寫在select裡;但select裡出現別的列就會報錯;
select sum(Age) from dba_data_files group by Name, Gender;

-- 但 select 裡出現別的列就會報錯,例:
select Weight, sum(Age) from dba_data_files group by Name, Gender;
  1. 同時查詢分組函式和非分組函式,並且必須將分組函式以外的所有的列(Name 和 Gender),都寫到group by裡,少一個都不行;
select Name, Gender, sum(Age) from dba_data_files group by Name, Gender;

不管select是否使用了where子句,都可以使用group by子句

三、rowid

rowid簡介

rowid是一個用來唯一標記表中行的偽列。它是物理表中行資料的內部地址,包含兩個地址,其一為指向資料表中包含該行的塊所存放資料檔案的地址,另一個是可以直接定位到資料行自身的這一行在資料塊中的地址。
除了在同一聚簇中可能不唯一外,每條記錄的rowid是唯一的。可以理解成rowid就是唯一的。

rowid解析

從Oracle 8i開始使用擴充套件rowid標識行實體地址
擴充套件rowid使用base64編碼行的實體地址,編碼字元包含A-Z, a-z, 0-9, +, 和/。
擴充套件rowid由四部分組成:OOOOOOOFFFBBBBBBRRR:
rowid包含如下內容:
①:物件所在的資料檔案號
②:物件所在的塊號
③:物件所在行在塊內的位置
④:物件號
其中:
OOOOOO:資料物件編號(6位顯示)
FFF:相關資料檔案編號(3位顯示)
BBBBBB:資料塊編號(6位顯示)
RRR:資料塊中行編號(3位顯示)
在這裡插入圖片描述

rowid示例

利用rowid結合maxmin函式快速去重

select t.* from bill t where t.rowid = (select max(s.rowid) from bill s 
where t.FLAG = s.FLAG
  and s.btype = 1
  and s.CODE in ('71131702422','71130427253','71134427859')
);

利用rowid結合maxmin函式快速刪除重複資料

-- 使用min函式的時候用大於號>
delete t.* from bill t where t.rowid < (select max(s.rowid) from bill s 
where t.FLAG = s.FLAG
  and s.btype = 1
  and s.CODE in ('71131702422','71130427253','71134427859')
);

本文參考連結1.

Mysql裡,可以用Max函式,類似於Oraclerowidmax
SQL Server中也有First_ValueLast_Value函式,可以用來實現。

注:group by 必須放在 order by 和 limit之前,不然會報錯