2012-01-12 15 views
7

Si consideri la seguente tabella:SQL: Rimozione di record duplicati - seppur diverso tipo

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

ritengo, i record {1,2, A} e {2, 1, A} come duplicato. Devo selezionare e produrre il set di record seguente:

  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 

Ho provato le seguenti domande. Ma inutilmente.

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. 

O anche questo:

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 

Entrambi non ha funzionato.

Il database dovrebbe essere Oracle 10g. Alla ricerca di una soluzione SQL pura. Ogni aiuto è apprezzato

+0

Che cosa stai cercando di realizzare? Per favore, espandi questo. – simchona

+0

Ho bisogno di un SQL per produrre il set di record {1, 2, A}, {2, 3, C} e {3, 4, D}. Per me {1, 2, A} e {2, 1, A} sono record duplicati e il set di risultati dovrebbe avere solo una tupla (o {1, 2, A} o {2, 1, A}, ma non entrambi) –

+0

Giusto per essere chiari, con "rimuovi" intendi * filtro dal set di risultati * piuttosto che * cancella *. – APC

risposta

6

Utilizzare le funzioni GREATEST() e ALTO() per identificare i valori comuni su più colonne. Quindi usa DISTINCT per scoprire i duplicati.

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

Questo ti dà il set di record preciso che hai chiesto. Ma le cose diventeranno più complicate se è necessario includere altre colonne da T6.


"Ma mi chiedevo se questo lavoro per i campi VARCHAR2 anche?"

Sì, ma utilizzerà i valori ASCII per determinare l'ordine, che non è sempre quello che ci si potrebbe aspettare (o desiderare).

"Inoltre, la mia tabella T6 potrebbe avere decine di migliaia di record."

Questo non è un sacco di dati in termini di oggi. Il DISTINCT causerà un ordinamento, che dovrebbe essere in grado di adattarsi alla memoria a meno che A e B siano davvero lunghe colonne VARCHAR2 - ma probabilmente anche allora.

Se questa è una query che si sta andando a voler correre molto, allora si può costruire un indice basato su funzioni di soddisfarla:

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

Ma mi sarebbe davvero preoccuparsi solo se si dispone di un vero e proprio problema di prestazioni con la query.

+0

Grazie @APC, non ho potuto controllare questo ora. Ma mi stavo chiedendo se questo funzionerà anche per i campi VARCHAR2?Inoltre, la mia tabella T6 potrebbe avere decine di migliaia di record. Apprezzo la tua risposta, ma StackOverflow non mi consente ancora di votare. :( –

0

Se l'ordine delle colonne A e B non importa e sempre contengono un numero intero, come su:

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