2012-01-12 62 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