SQL:删除重复记录 - 虽然不同类型

时间:2012-01-12 04:03:40

标签: sql oracle duplicate-data duplicate-removal

考虑下表:

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解决方案。感谢每一位帮助。

2 个答案:

答案 0 :(得分: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 )
/

但如果您对查询有真正的性能问题,我真的很烦。

答案 1 :(得分:0)

如果A列和B列的顺序无关紧要并且始终包含整数,那么如何:

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