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

G P*_*G P 7 sql oracle duplicate-data duplicate-removal

请考虑下表:

TAB6
         A          B C
---------- ---------- -
         1          2 A
         2          1 A
         2          3 C
         3          4 D
Run Code Online (Sandbox Code Playgroud)

我认为,记录{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
Run Code Online (Sandbox Code Playgroud)

我尝试了以下查询.但无济于事.

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.
Run Code Online (Sandbox Code Playgroud)

甚至这个:

 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
Run Code Online (Sandbox Code Playgroud)

两者都没用.

该数据库将是Oracle 10g.寻找纯SQL解决方案.感谢每一位帮助.

APC*_*APC 6

使用GREATEST()和LEAST()函数来标识多列中的公共值.然后使用DISTINCT来删除重复项.

select distinct least(a, b) as a
       , greatest(a, b) as b
       , c
from t6 
Run Code Online (Sandbox Code Playgroud)

这为您提供了所要求的精确记录集.但是如果您需要包含T6中的其他列,事情会变得更复杂.


"但我想知道这对VARCHAR2字段是否也适用?"

是的,但它将使用ASCII值来确定顺序,这并不总是您可能期望(或期望).

"另外,我的桌子T6可能有数万条记录."

在今天的条款中,这真的不是很多数据.DISTINCT将导致一个排序,它应该能够适应内存,除非A并且B实际上是很长的VARCHAR2列 - 但可能甚至是这样.

如果这是一个你想要运行很多的查询,那么你可以构建一个基于函数的索引来满足它:

create index t6_fbi on t6(least(a, b)
                           , greatest(a, b)
                           , c )
/
Run Code Online (Sandbox Code Playgroud)

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