Eu tenho uma tabela com uma coluna varchar e gostaria de encontrar todos os registros que tenham valores duplicados nesta coluna. Qual é a melhor consulta que posso usar para encontrar as duplicatas?
Eu tenho uma tabela com uma coluna varchar e gostaria de encontrar todos os registros que tenham valores duplicados nesta coluna. Qual é a melhor consulta que posso usar para encontrar as duplicatas?
Respostas:
Faça um SELECT
com uma GROUP BY
cláusula. Digamos que nome é a coluna na qual você deseja encontrar duplicatas:
SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 1;
Isso retornará um resultado com o valor do nome na primeira coluna e uma contagem de quantas vezes esse valor aparece na segunda.
GROUP_CONCAT(id)
e ele listará os IDs. Veja minha resposta para um exemplo.
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
)
Essa consulta retorna registros completos, não apenas distintos varchar_column
.
Esta consulta não usa COUNT(*)
. Se houver muitas duplicatas, COUNT(*)
for caro e você não precisar do todo COUNT(*)
, precisará saber se há duas linhas com o mesmo valor.
Ter um índice ativado varchar_column
irá, obviamente, acelerar bastante essa consulta.
ORDER BY varchar_column DESC
ao final da consulta.
GROUP BY
e HAVING
retorna apenas uma das possíveis duplicatas. Além disso, desempenho com campo indexado em vez de COUNT(*)
e a possibilidade ORDER BY
de agrupar registros duplicados.
Com base na resposta da levik para obter os IDs das linhas duplicadas, você pode fazer isso GROUP_CONCAT
se o seu servidor suportar (isso retornará uma lista de IDs separados por vírgula).
SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUP BY name HAVING c > 1;
SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]
ele permite a edição em linha e deve atualizar todas as linhas envolvidas (ou pelo menos a primeira que corresponda), mas infelizmente a edição gera um erro de Javascript. ..
Supondo que sua tabela se chame TableABC e a coluna que você deseja seja Col e a chave primária para T1 seja Key.
SELECT a.Key, b.Key, a.Col
FROM TableABC a, TableABC b
WHERE a.Col = b.Col
AND a.Key <> b.Key
A vantagem dessa abordagem sobre a resposta acima é que ela fornece a chave.
Para descobrir quantos registros estão duplicados na coluna de nome em Funcionário, a consulta abaixo é útil;
Select name from employee group by name having count(*)>1;
para obter todos os dados que contêm duplicação, usei isso:
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 = a tabela com a qual você está trabalhando.
DupliactedData = os dados duplicados que você está procurando.
Minha consulta final incorporou algumas das respostas aqui que ajudaram - combinando agrupar por, contar & GROUP_CONCAT.
SELECT GROUP_CONCAT(id), `magento_simple`, COUNT(*) c
FROM product_variant
GROUP BY `magento_simple` HAVING c > 1;
Isso fornece a identificação dos dois exemplos (separados por vírgula), o código de barras que eu precisava e quantas duplicatas.
Mude a tabela e as colunas adequadamente.
Não estou vendo nenhuma abordagem JOIN, que tem muitos usos em termos de duplicatas.
Essa abordagem fornece resultados dobrados reais.
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
Substitua cidade pela sua mesa. Substitua nome pelo nome do seu campo
Levando a resposta do @ maxyfc adiante, eu precisava encontrar todas as linhas retornadas com os valores duplicados, para poder editá-las no MySQL Workbench :
SELECT * FROM table
WHERE field IN (
SELECT field FROM table GROUP BY field HAVING count(*) > 1
) ORDER BY field
Vi o resultado acima e a consulta funcionará bem se você precisar verificar o valor da coluna única duplicada. Por exemplo, email.
Mas se você precisar verificar com mais colunas e desejar verificar a combinação do resultado, para que esta consulta funcione bem:
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
Eu prefiro usar funções em janelas (MySQL 8.0+) para encontrar duplicatas porque eu podia ver a linha inteira:
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
A seguir, você encontrará todos os product_id usados mais de uma vez. Você obtém apenas um registro para cada product_id.
SELECT product_id FROM oc_product_reward GROUP BY product_id HAVING count( product_id ) >1
Código extraído de: 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
para a.*
e obter todos os IDs das linhas com duplicatas.
SELECT DISTINCT a.*
resolvido quase instantaneamente.
Para remover linhas duplicadas com vários campos, primeiro cancele-as na nova chave exclusiva especificada para as únicas linhas distintas e, em seguida, use o comando "agrupar por" para remover as linhas duplicadas com a mesma nova chave exclusiva:
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 ...
? Uma pequena explicação da sua solução seria ótima.
Uma contribuição muito tardia ... no caso de ajudar alguém a passar o tempo ... eu tinha a tarefa de encontrar pares de transações correspondentes (na verdade, ambos os lados das transferências de conta para conta) em um aplicativo bancário, para identificar quais eram 'de' e 'para' para cada transação de transferência entre contas, então acabamos com isso:
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;
O resultado é que ele DuplicateResultsTable
fornece linhas contendo transações correspondentes (ou seja, duplicadas), mas também fornece os mesmos IDs de transação ao contrário na segunda vez em que corresponde ao mesmo par; portanto, o externo SELECT
está lá para agrupar pelo primeiro ID de transação, o que é feito usando LEAST
e GREATEST
para garantir que as duas transações sejam sempre da mesma ordem nos resultados, o que a torna segura GROUP
pela primeira, eliminando todas as correspondências duplicadas. Percorreu quase um milhão de registros e identificou mais de 12.000 partidas em menos de 2 segundos. É claro que o transactionid é o índice principal, o que realmente ajudou.
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 você deseja remover o uso duplicado DISTINCT
Caso contrário, use esta consulta:
SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;
Tente usar esta consulta:
SELECT name, COUNT(*) value_count FROM company_master GROUP BY name HAVING value_count > 1;