Come trovare i duplicati in 2 colonne non 1


107

Ho una tabella di database MySQL con due colonne che mi interessano. Individualmente possono avere ciascuno dei duplicati, ma non dovrebbero mai avere un duplicato di ENTRAMBI con lo stesso valore.

stone_idpuò avere duplicati purché per ogni upshargetitolo sia diverso e al contrario. Ma diciamo per esempio stone_id= 412 e upcharge_title= "zaffiro" che la combinazione dovrebbe verificarsi solo una volta.

Questo va bene:

stone_id = 412 upcharge_title = "sapphire"
stone_id = 412 upcharge_title = "ruby"

Questo NON va bene:

stone_id = 412 upcharge_title = "sapphire"
stone_id = 412 upcharge_title = "sapphire"

Esiste una query che troverà duplicati in entrambi i campi? E se possibile, c'è un modo per impostare il mio database in modo da non consentirlo?

Sto usando MySQL versione 4.1.22

Risposte:


192

È necessario impostare una chiave composta tra i due campi. Ciò richiederà un stone_id e un upcharge_title univoci per ogni riga.

Per quanto riguarda la ricerca dei duplicati esistenti, prova questo:

select   stone_id,
         upcharge_title,
         count(*)
from     your_table
group by stone_id,
         upcharge_title
having   count(*) > 1

Grazie, questo li seleziona. Potresti essere così gentile da dirmi come cancellare i duplicati (ma lascia 1 copia ovviamente) GRAZIE !!
JD Isaacks

2
Un modo sarebbe prendere tutti i dati distinti e ricreare la tabella.
Miyagi Coder

1
@ John Isaacks: Se non ci sono altri campi con cui puoi distinguerli (cioè tutti i campi sono duplicati), allora dovrai cancellare entrambe le righe e ricrearne una. Un modo sarebbe copiare i duplicati in una copia della tabella, eliminarli dall'originale e reinserire righe distinte dalla copia.
P Daddy

Questo non funziona su postgres 8.1, qualcuno potrebbe darmi una mano?
Lennon

grazie mille, l'ordine che raggruppa per argomento?
Andrew

35

Ho trovato utile aggiungere un indice unqiue usando un "ALTER IGNORE" che rimuove i duplicati e applica i record univoci che suona come vorresti fare. Quindi la sintassi sarebbe:

ALTER IGNORE TABLE `table` ADD UNIQUE INDEX(`id`, `another_id`, `one_more_id`);

Questo aggiunge efficacemente il vincolo univoco, il che significa che non avrai mai record duplicati e IGNORE elimina i duplicati esistenti.

Puoi leggere di più su eh ALTER IGNORE qui: http://mediakey.dk/~cc/mysql-remove-duplicate-entries/

Aggiornamento: sono stato informato da @Inquisitive che questo potrebbe non riuscire nelle versioni di MySql> 5.5:

Non funziona su MySQL> 5.5 e su tabelle InnoDB e su Percona a causa della loro funzione di creazione rapida di indici InnoDB [ http://bugs.mysql.com/bug.php?id=40344] . In questo caso, prima esegui set session old_alter_table=1e poi il comando precedente funzionerà correttamente

Aggiornamento - ALTER IGNORERimosso nella 5.7

Dai documenti

A partire da MySQL 5.6.17, la clausola IGNORE è deprecata e il suo utilizzo genera un avviso. IGNORE viene rimosso in MySQL 5.7.

Uno degli sviluppatori di MySQL offre due alternative :

  • Raggruppa per campi univoci ed elimina come visto sopra
  • Crea una nuova tabella, aggiungi un indice univoco, usa INSERT IGNORE, ad esempio:
CREATE TABLE duplicate_row_table LIKE regular_row_table;
ALTER TABLE duplicate_row_table ADD UNIQUE INDEX (id, another_id);
INSERT IGNORE INTO duplicate_row_table SELECT * FROM regular_row_table;
DROP TABLE regular_row_table;
RENAME TABLE duplicate_row_table TO regular_row_table;

Ma a seconda delle dimensioni del tuo tavolo, questo potrebbe non essere pratico


1
Vero, ma almeno per la prossima volta lo sai. Ho avuto lo stesso problema e ho pensato che fosse utile condividerlo con gli altri
SeanDowney

Stavo solo scherzando sul fatto che fosse in ritardo di 3 anni. Sono davvero contento che tu abbia condiviso. Da qui il vantaggio 1.
JD Isaacks

Immagino che questo rimuova uno dei duplicati arbitrariamente, quindi assicurati che non ci siano dati diversi tra ogni riga che potrebbe essere utile conoscere o conservare.
Joshua Pinter

+1 per la risposta anche dopo 2 anni di ritardo. Ho cancellato accidentalmente una chiave composita e questo è stato un salvavita. Grazie
ivcode

Ho provato alcune tecniche di ricerca dei duplicati e nessuna di queste era così semplice e veloce. Grazie per aver condiviso questo metodo.
Kristjan O.

8

Puoi trovare duplicati come questo ..

Select
    stone_id, upcharge_title, count(*)
from 
    particulartable
group by 
    stone_id, upcharge_title
having 
    count(*) > 1

4

Per trovare i duplicati:

select stone_id, upcharge_title from tablename group by stone_id, upcharge_title having count(*)>1

Per evitare che ciò accada in futuro, creare una chiave univoca composta su questi due campi.


1
Grazie mille, puoi dirmi come eliminare tutti i duplicati tranne uno. E come faccio a impostare una chiave composta in phpmyadmin. GRAZIE!!!
JD Isaacks

3

Per inciso, un vincolo univoco composito sul tavolo impedirebbe che ciò si verifichi in primo luogo.

ALTER TABLE table
    ADD UNIQUE(stone_id, charge_title)

(Questo è un T-SQL valido. Non sono sicuro di MySQL.)


1
Penso che funzioni ma non me lo consentirà fino a quando non rimuoverò prima i duplicati. Grazie.
JD Isaacks

1

questo post SO mi ha aiutato, ma anch'io volevo sapere come eliminare e mantenere una delle righe ... ecco una soluzione PHP per eliminare le righe duplicate e mantenerne una (nel mio caso c'erano solo 2 colonne ed è in un funzione per cancellare associazioni di categorie duplicate)

$dupes = $db->query('select *, count(*) as NUM_DUPES from PRODUCT_CATEGORY_PRODUCT group by fkPRODUCT_CATEGORY_ID, fkPRODUCT_ID having count(*) > 1');
if (!is_array($dupes))
    return true;
foreach ($dupes as $dupe) {
    $db->query('delete from PRODUCT_CATEGORY_PRODUCT where fkPRODUCT_ID = ' . $dupe['fkPRODUCT_ID'] . ' and fkPRODUCT_CATEGORY_ID = ' . $dupe['fkPRODUCT_CATEGORY_ID'] . ' limit ' . ($dupe['NUM_DUPES'] - 1);
}

il (limite NUM_DUPES - 1) è ciò che preserva la singola riga ...

ringrazia tutti


3
ALTER IGNORE TABLE table ADD UNIQUE INDEX index_name(stone_id, charge_title)rimuoverà le righe duplicate lasciando solo una coppia unica.
dev-null-dweller
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.