2017-01-03 66 views
2

我有興趣從我的表中刪除重複的行。 重複我指的是兩行或更多行,所有行都包含相同的值。 在網上找到了多種方法,所有最終都涉及到連接或分組,而所有感興趣的列都應該明確命名。 這並不困難,但需要爲每個新表編寫列, ,並且如果涉及數百個列,可能會很繁瑣。Oracle - 使用union刪除重複的行 - 是否真的有效?

這是一個天真的問題:聯合刪除重複的行權? 可以通用的查詢是:

create table new_table as 
(
select * from old_table 
union 
select * from old_table 
) 

如下面的例子:

with tmp as 
(
select 1 as a, 2 as b from dual 
union all 
select 1 as a, 2 as b from dual 
) 
select * from tmp 
union 
select * from tmp 

A B 
- - 
1 2 

這似乎是一個簡單的解決方案,它不需要任何配置,但表名。

我錯過了什麼?或者這是完全有效的?

謝謝

+3

這是完全有效的。我會添加一條評論,說' - 有意使用聯盟刪除重複「。 –

+3

使用'select distinct * from old_table'有什麼問題? –

+1

'UNION'是'UNION DISTINCT'的縮寫。 (和'SELECT'是'SELECT ALL'的簡寫形式...) – jarlh

回答

2

您的方法是有效的,它的工作原理。我覺得更好的方法是使用DISTINCT這個關鍵字來達到這個目的。

select * from test; 
A B 
------ 
1 2 
1 2 
1 2 
1 2 
1 2 

    select distinct * from test 
    A B 
    ------- 
    1 2 
2

你的方法是正確的,但效率不高,(恕我直言)過於複雜。

我做了一個簡單的測試用類似下面的表格:

create table old_table(a number, b number); 
begin 
    for i in 1..5 loop 
     insert into old_table select level, -level from dual connect by level <= 1000000; 
     commit; 
    end loop; 
end; 

隨着UNION你:

create table new_table as 
(
    select * from old_table 
    UNION 
    select * from old_table 
); 
-------------------------------------------------------------------------------------------- 
| Id | Operation    | Name  | Rows | Bytes |TempSpc| Cost (%CPU)| Time  | 
-------------------------------------------------------------------------------------------- 
| 0 | CREATE TABLE STATEMENT |   | 9934K| 246M|  | 86405 (51)| 00:17:17 | 
| 1 | LOAD AS SELECT  | NEW_TABLE |  |  |  |   |   | 
| 2 | SORT UNIQUE   |   | 9934K| 246M| 343M| 86405 (51)| 00:17:17 | 
| 3 | UNION-ALL   |   |  |  |  |   |   | 
| 4 |  TABLE ACCESS FULL | OLD_TABLE | 4967K| 123M|  | 3039 (1)| 00:00:37 | 
| 5 |  TABLE ACCESS FULL | OLD_TABLE | 4967K| 123M|  | 3039 (1)| 00:00:37 | 
-------------------------------------------------------------------------------------------- 

您可以嘗試通過在第二應用過濾器,以簡化UNION掃描表格:

create table new_table1 as 
(
    select * from old_table 
    UNION 
    select * from old_table where null is not null 
); 
-------------------------------------------------------------------------------------------- 
| Id | Operation    | Name  | Rows | Bytes |TempSpc| Cost (%CPU)| Time  | 
-------------------------------------------------------------------------------------------- 
| 0 | CREATE TABLE STATEMENT |   | 4967K| 123M|  | 43291 (1)| 00:08:40 | 
| 1 | LOAD AS SELECT  | NEW_TABLE |  |  |  |   |   | 
| 2 | SORT UNIQUE   |   | 4967K| 123M| 171M| 43291 (1)| 00:08:40 | 
| 3 | UNION-ALL   |   |  |  |  |   |   | 
| 4 |  TABLE ACCESS FULL | OLD_TABLE | 4967K| 123M|  | 3039 (1)| 00:00:37 | 
|* 5 |  FILTER    |   |  |  |  |   |   | 
| 6 |  TABLE ACCESS FULL | OLD_TABLE | 4967K| 123M|  | 3039 (1)| 00:00:37 | 
-------------------------------------------------------------------------------------------- 

這就是DISTINCT作用:

create table new_table2 as 
(
    select distinct * from old_table 
); 
--------------------------------------------------------------------------------------------- 
| Id | Operation    | Name  | Rows | Bytes |TempSpc| Cost (%CPU)| Time  | 
--------------------------------------------------------------------------------------------- 
| 0 | CREATE TABLE STATEMENT |   | 4967K| 123M|  | 43203 (1)| 00:08:39 | 
| 1 | LOAD AS SELECT  | NEW_TABLE2 |  |  |  |   |   | 
| 2 | HASH UNIQUE   |   | 4967K| 123M| 171M| 39759 (1)| 00:07:58 | 
| 3 | TABLE ACCESS FULL | OLD_TABLE | 4967K| 123M|  | 3039 (1)| 00:00:37 | 
--------------------------------------------------------------------------------------------- 

無論方法,結果是一樣的,沒有必要明確寫入所有列名:

SQL> select count(1) from new_table union all 
    2 select count(1) from new_table1 union all 
    3 select count(1) from new_table2; 

    COUNT(1) 
---------- 
    1000000 
    1000000 
    1000000