2012-01-03 9 views
8

Ho una tabella con 6 colonne:visualizzare tutti i dati per righe duplicate in Oracle

  • id
  • name
  • type_id
  • code
  • lat
  • long

I primi tre sono obbligatori. ID è la chiave privata, inserita automaticamente con una sequenza.

Ho alcune righe duplicate, come definito da ENTRAMBI i valori name e type_id uguali, ma mi piacerebbe visualizzare tutti i dati per i duplicati. Riesco a trovare i duplicati semplicemente:

SELECT name 
     , type_id 
FROM table1 
GROUP BY name 
     , type_id 
HAVING COUNT(*) > 1 

ma in realtà la visualizzazione di tutte le informazioni mi confonde. So che questo dovrebbe essere semplice, ma qui sto colpendo un muro.

risposta

15

È sempre possibile utilizzare la query GROUP BY/HAVING in una clausola IN. Questo funziona ed è relativamente semplice ma potrebbe non essere particolarmente efficiente se il numero di righe duplicate è relativamente grande.

Sarebbe generalmente più efficiente utilizzare le funzioni analitiche per evitare di colpire il tavolo una seconda volta.

SELECT * 
    FROM (SELECT id, 
       name, 
       type_id, 
       code, 
       lat, 
       long, 
       count(*) over (partition by name, type_id) cnt 
      FROM table1) 
WHERE cnt > 1 

A seconda di cosa si sta progettando di fare con i dati e quanti duplicati di una riga particolare ci potrebbe essere, si potrebbe anche voler aderire table1 a se stesso per ottenere i dati in una singola riga

SELECT a.name, 
     a.type_id, 
     a.id, 
     b.id, 
     a.code, 
     b.code, 
     a.lat, 
     b.lat, 
     a.long, 
     b.long 
    FROM table1 a 
     JOIN table1 b ON (a.name = b.name AND 
         a.type_id = b.type_id AND 
         a.rowid > b.rowid) 
+0

Il mio primo pensiero è stato la prima query, ma non sapevo se potevi usare due colonne in una clausola IN. Credo che avrei dovuto provarci. Grazie. – Marc

1
SELECT * 
FROM table1 t1 
WHERE (t1.name,t1.type_id) in (SELECT DISTINCT name 
               , type_id 
           FROM  table1 
           GROUP BY name, type_id 
           HAVING COUNT(*) > 1) 

Lo farei.

HTH

1

È possibile fare un auto join sul tavolo per trovare tutte le coppie di duplicati:

SELECT 
    a.name name 
, a.type_id type_id_a 
, a.code code_a 
, a.lat  lat_a 
, a.long long_a 
, b.code code_b 
, b.lat  lat_b 
, b.long long_b 
FROM table1 a 
JOIN table1 b 
ON a.name = b.name 
AND a.type_id = b.type_id 
AND a.ROWID > b.ROWID 

Per assicurarsi che una riga non corrisponde se stessa e ogni coppia viene emesso solo una volta, Ho aggiunto a.ROWID > b.ROWID, che funziona per Oracle. Avrai bisogno di un modo diverso per tenerli separati se usi un database diverso.

+0

Presumibilmente, si desidera una condizione di join aggiuntiva per garantire che la riga restituita da 'A' e da' B' siano in realtà diverse righe. Qualcosa come 'AND a.id> b.id' o 'AND a.rowid> b.rowid' –

+0

Grazie, ho aggiornato la risposta. –

0

Che ancora non trova il doppio se uno dei campi confrontati ha un valore NULL. Per ottenere quelli, io uso nvl per rel legare NULL nei campi confrontati con un valore che so non può verificarsi in quella tabella/campo.

-2

Basta fare i NULLS 0 ...

... utilizzare la funzione NVL.

Problemi correlati