Ho una tabella con una colonna varchar e vorrei trovare tutti i record che hanno valori duplicati in questa colonna. Qual è la migliore query che posso usare per trovare i duplicati?
Ho una tabella con una colonna varchar e vorrei trovare tutti i record che hanno valori duplicati in questa colonna. Qual è la migliore query che posso usare per trovare i duplicati?
Risposte:
Fai un SELECT
con una GROUP BY
clausola. Diciamo che il nome è la colonna in cui vuoi trovare i duplicati:
SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 1;
Ciò restituirà un risultato con il valore del nome nella prima colonna e un conteggio di quante volte quel valore appare nella seconda.
GROUP_CONCAT(id)
ed elencherà gli ID. Vedi la mia risposta per un esempio.
ERROR: column "c" does not exist LINE 1
?
SELECT varchar_col
FROM table
GROUP BY varchar_col
HAVING COUNT(*) > 1;
IN()
/ NOT IN()
.
SELECT *
FROM mytable mto
WHERE EXISTS
(
SELECT 1
FROM mytable mti
WHERE mti.varchar_column = mto.varchar_column
LIMIT 1, 1
)
Questa query restituisce record completi, non solo di quelli distinti varchar_column
.
Questa query non utilizza COUNT(*)
. Se ci sono molti duplicati, COUNT(*)
è costoso e non hai bisogno del tutto COUNT(*)
, devi solo sapere se ci sono due righe con lo stesso valore.
Avere un indice varchar_column
attivo ovviamente accelererà notevolmente questa query.
ORDER BY varchar_column DESC
alla fine della query.
GROUP BY
e HAVING
restituisce solo uno dei possibili duplicati. Inoltre, prestazioni con campo indicizzato anziché COUNT(*)
e possibilità ORDER BY
di raggruppare record duplicati.
Costruendo la risposta di levik per ottenere gli ID delle righe duplicate, puoi fare un GROUP_CONCAT
caso se il tuo server lo supporta (questo restituirà un elenco di ID separati da virgole).
SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUP BY name HAVING c > 1;
SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]
abilita la modifica in linea e dovrebbe aggiornare tutte le righe coinvolte (o almeno la prima corrispondente), ma sfortunatamente la modifica genera un errore Javascript. ..
Supponendo che la tabella sia denominata TableABC e la colonna desiderata sia Col e la chiave primaria per T1 è Key.
SELECT a.Key, b.Key, a.Col
FROM TableABC a, TableABC b
WHERE a.Col = b.Col
AND a.Key <> b.Key
Il vantaggio di questo approccio rispetto alla risposta sopra è che fornisce la chiave.
Per trovare quanti record sono duplicati nella colonna del nome in Employee, la query di seguito è utile;
Select name from employee group by name having count(*)>1;
per ottenere tutti i dati che contengono duplicazioni ho usato questo:
SELECT * FROM TableName INNER JOIN(
SELECT DupliactedData FROM TableName GROUP BY DupliactedData HAVING COUNT(DupliactedData) > 1 order by DupliactedData)
temp ON TableName.DupliactedData = temp.DupliactedData;
TableName = la tabella con cui stai lavorando.
DupliactedData = i dati duplicati che stai cercando.
La mia query finale includeva alcune delle risposte che mi hanno aiutato - combinando gruppo per, conteggio e GROUP_CONCAT.
SELECT GROUP_CONCAT(id), `magento_simple`, COUNT(*) c
FROM product_variant
GROUP BY `magento_simple` HAVING c > 1;
Ciò fornisce l'id di entrambi gli esempi (separati da virgola), il codice a barre di cui avevo bisogno e quanti duplicati.
Modifica la tabella e le colonne di conseguenza.
Non vedo alcun approccio JOIN, che ha molti usi in termini di duplicati.
Questo approccio offre risultati raddoppiati.
SELECT t1.* FROM my_table as t1
LEFT JOIN my_table as t2
ON t1.name=t2.name and t1.id!=t2.id
WHERE t2.id IS NOT NULL
ORDER BY t1.name
SELECT t.*,(select count(*) from city as tt
where tt.name=t.name) as count
FROM `city` as t
where (
select count(*) from city as tt
where tt.name=t.name
) > 1 order by count desc
Sostituisci la città con il tuo tavolo. Sostituisci il nome con il nome del campo
Prendendo ulteriormente la risposta di @ maxyfc , dovevo trovare tutte le righe restituite con i valori duplicati, in modo da poterle modificare in MySQL Workbench :
SELECT * FROM table
WHERE field IN (
SELECT field FROM table GROUP BY field HAVING count(*) > 1
) ORDER BY field
Ho visto il risultato sopra e la query funzionerà bene se è necessario controllare il valore di una singola colonna che è duplicato. Ad esempio e-mail.
Ma se è necessario verificare con più colonne e si desidera verificare la combinazione del risultato, questa query funzionerà correttamente:
SELECT COUNT(CONCAT(name,email)) AS tot,
name,
email
FROM users
GROUP BY CONCAT(name,email)
HAVING tot>1 (This query will SHOW the USER list which ARE greater THAN 1
AND also COUNT)
SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
Preferisco usare le funzioni con finestra (MySQL 8.0+) per trovare duplicati perché ho potuto vedere l'intera riga:
WITH cte AS (
SELECT *
,COUNT(*) OVER(PARTITION BY col_name) AS num_of_duplicates_group
,ROW_NUMBER() OVER(PARTITION BY col_name ORDER BY col_name2) AS pos_in_group
FROM table
)
SELECT *
FROM cte
WHERE num_of_duplicates_group > 1;
SELECT
t.*,
(SELECT COUNT(*) FROM city AS tt WHERE tt.name=t.name) AS count
FROM `city` AS t
WHERE
(SELECT count(*) FROM city AS tt WHERE tt.name=t.name) > 1 ORDER BY count DESC
Di seguito troverai tutti i product_id utilizzati più di una volta. Ottieni un solo record per ogni product_id.
SELECT product_id FROM oc_product_reward GROUP BY product_id HAVING count( product_id ) >1
Codice tratto da: http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-any.html
CREATE TABLE tbl_master
(`id` int, `email` varchar(15));
INSERT INTO tbl_master
(`id`, `email`) VALUES
(1, 'test1@gmail.com'),
(2, 'test2@gmail.com'),
(3, 'test1@gmail.com'),
(4, 'test2@gmail.com'),
(5, 'test5@gmail.com');
QUERY : SELECT id, email FROM tbl_master
WHERE email IN (SELECT email FROM tbl_master GROUP BY email HAVING COUNT(id) > 1)
SELECT DISTINCT a.email FROM `users` a LEFT JOIN `users` b ON a.email = b.email WHERE a.id != b.id;
a.email
a a.*
e ottenere tutti gli ID delle righe con i duplicati.
SELECT DISTINCT a.*
risolto quasi istantaneamente.
Per rimuovere le righe duplicate con più campi, prima cancellale nella nuova chiave univoca specificata per le sole righe distinte, quindi usa il comando "raggruppa per" per rimuovere le righe duplicate con la stessa nuova chiave univoca:
Create TEMPORARY table tmp select concat(f1,f2) as cfs,t1.* from mytable as t1;
Create index x_tmp_cfs on tmp(cfs);
Create table unduptable select f1,f2,... from tmp group by cfs;
CREATE TEMPORARY TABLE ...
? Una piccola spiegazione della tua soluzione sarebbe ottima.
Un contributo molto tardi ... nel caso in cui aiuti qualcuno a smettere di fumare ... Avevo il compito di trovare coppie di transazioni corrispondenti (in realtà entrambi i lati dei trasferimenti da conto a conto) in un'app bancaria, per identificare quali erano il 'da' e il 'a' per ogni transazione di trasferimento tra account, quindi abbiamo finito con questo:
SELECT
LEAST(primaryid, secondaryid) AS transactionid1,
GREATEST(primaryid, secondaryid) AS transactionid2
FROM (
SELECT table1.transactionid AS primaryid,
table2.transactionid AS secondaryid
FROM financial_transactions table1
INNER JOIN financial_transactions table2
ON table1.accountid = table2.accountid
AND table1.transactionid <> table2.transactionid
AND table1.transactiondate = table2.transactiondate
AND table1.sourceref = table2.destinationref
AND table1.amount = (0 - table2.amount)
) AS DuplicateResultsTable
GROUP BY transactionid1
ORDER BY transactionid1;
Il risultato è che DuplicateResultsTable
fornisce righe contenenti transazioni corrispondenti (cioè duplicate), ma fornisce anche gli stessi ID transazione al contrario la seconda volta che corrisponde alla stessa coppia, quindi l'esterno SELECT
è lì per raggruppare per il primo ID transazione, che viene fatto usando LEAST
e GREATEST
per assicurarsi che i due transazioniid siano sempre nello stesso ordine nei risultati, il che lo rende sicuro GROUP
dal primo, eliminando così tutte le corrispondenze duplicate. Ha superato quasi un milione di record e identificato oltre 12.000 partite in poco meno di 2 secondi. Ovviamente il Transactionid è l'indice primario, che ha davvero aiutato.
Select column_name, column_name1,column_name2, count(1) as temp from table_name group by column_name having temp > 1
SELECT ColumnA, COUNT( * )
FROM Table
GROUP BY ColumnA
HAVING COUNT( * ) > 1
Se si desidera rimuovere l'uso duplicato DISTINCT
Altrimenti usa questa query:
SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;
Prova a usare questa query:
SELECT name, COUNT(*) value_count FROM company_master GROUP BY name HAVING value_count > 1;