2012-01-12 103 views
7

考慮下表:SQL:刪除重複記錄 - 儘管是在不同類型的

TAB6 
     A   B C 
---------- ---------- - 
     1   2 A 
     2   1 A 
     2   3 C 
     3   4 D 

我認爲,這些記錄{1,2,A}和{2,1,A}爲重複。我需要選擇並生成以下記錄集:

  A   B C      A   B C 
---------- ---------- -    ---------- ---------- - 
     1   2 A   or   2   1 A 
     2   3 C      2   3 C 
     3   4 D      3   4 D 

我試過了下面的查詢。但無濟於事。

select t1.* 
from t6 t1 
, t6 t2 
where t1.a <> t2.b 
and t1.b <> t2.a 
and t1.rowid <> t2.rowid 
/

     A   B C 
---------- ---------- - 
     1   2 A 
     2   1 A 
     2   1 A 
     2   3 C 
     3   4 D 
     3   4 D 

6 rows selected. 

甚至這樣的:

select * 
from t6 t1 
where exists (select * from t6 t2 where t1.a <> t2.b and t1.b <> t2.a) 
/
     A   B C 
---------- ---------- - 
     1   2 A 
     2   1 A 
     2   3 C 
     3   4 D 

兩人都沒有工作。

該數據庫將是Oracle 10g。尋找純粹的SQL解決方案。每一個幫助表示讚賞。

+0

究竟是你想實現什麼目標?請在此擴展。 – simchona 2012-01-12 04:05:27

+0

我需要一個SQL來產生記錄集{1,2,A},{2,3,C}和{3,4,D}。對我來說{1,2,A}和{2,1,A}是重複的記錄,結果集應該只有一個元組({1,2,A}或{2,1,A}),但不能同時) – 2012-01-12 04:08:23

+0

只需要清楚,通過「刪除」你的意思是*從結果集*過濾而不是*刪除*。 – APC 2012-01-12 04:23:30

回答

6

使用GREATEST()和LEAST()函數來識別跨多列的公共值。然後使用DISTINCT來清除重複項。

select distinct least(a, b) as a 
     , greatest(a, b) as b 
     , c 
from t6 

這給你你要求的精確記錄集。但是如果您需要包含來自T6的其他列,事情會變得更加複雜。


「但我不知道這是否會爲VARCHAR2裏幹活也?」

是的,但它會使用ASCII值來確定順序,這並不總是您可能期望的(或期望)。

「另外,我的表T6可能有幾萬條記錄。」

按照今天的條件,這確實不是很多數據。 DISTINCT會導致排序,這應該能夠適應內存,除非AB確實是很長的VARCHAR2列 - 但可能即便如此。

如果這是你要要運行很多,那麼你可以建立一個基於函數的索引來滿足它的查詢:

create index t6_fbi on t6(least(a, b) 
          , greatest(a, b) 
          , c) 
/

但是,如果你有一個真正的我真的只是懶得查詢性能問題。

+0

謝謝@APC,我現在無法檢查。但我想知道這是否也適用於VARCHAR2字段?此外,我的表T6可能有數萬記錄..我感謝您的迴應,但仍Stackoverflow不允許我投票你呢。 :( – 2012-01-12 06:20:17

0

如果列A和B的順序並不重要,始終包含一個整數,怎麼樣:

select distinct 
    least(a, b) as a, 
    greatest(a, b) as b, 
    c 
from 
    t6