Encontrar valores duplicados en una tabla SQL

Es fácil encontrar duplicados con un campo:

SELECT name, COUNT(email) 
FROM users
GROUP BY email
HAVING COUNT(email) > 1

Entonces, si tenemos una mesa

ID   NAME   EMAIL
1    John   asd@asd.com
2    Sam    asd@asd.com
3    Tom    asd@asd.com
4    Bob    bob@asd.com
5    Tom    asd@asd.com

Esta consulta nos dará John, Sam, Tom, Tom porque todos tienen el mismo email.

Sin embargo, lo que quiero es obtener duplicados con el mismo email y name.

Es decir, quiero obtener "Tom", "Tom".

La razón por la que necesito esto: cometí un error y permití insertar un duplicado name y email valores. Ahora necesito eliminar / cambiar los duplicados, así que necesito encontrar ellos primero.

preguntado el 07 de abril de 10 a las 15:04

No creo que le permita seleccionar el nombre en su primera muestra, ya que no está en una función agregada. "¿Cuál es el recuento de direcciones de correo electrónico coincidentes y su nombre" es una lógica complicada ... -

Descubrí que esto no funciona con el servidor MSSQL debido a la name en el campo SELECT. -

lo que necesito es la identificación de los registros con correo electrónico duplicado -

estaba a punto de encontrar mis propios datos duplicados, así que esto funcionó para mí (en PHP hacer: if ($ record ['DuplicatesCount']> 1)): "SELECCIONAR código de barras, COUNT (*) AS DuplicatesCount FROM [main1]. [dbo ]. [bayan_product] GRUPO POR código de barras "-

30 Respuestas

SELECT
    name, email, COUNT(*)
FROM
    users
GROUP BY
    name, email
HAVING 
    COUNT(*) > 1

Simplemente agrupe en ambas columnas.

Nota: el estándar ANSI más antiguo es tener todas las columnas no agregadas en GROUP BY, pero esto ha cambiado con la idea de "dependencia funcional":

En la teoría de bases de datos relacionales, una dependencia funcional es una restricción entre dos conjuntos de atributos en una relación de una base de datos. En otras palabras, la dependencia funcional es una restricción que describe la relación entre atributos en una relación.

El soporte no es consistente:

Respondido el 01 de junio de 18 a las 12:06

@webXL DONDE trabaja con un solo registro HABIENDO trabaja con un grupo - bjan

@gbn ¿Es posible incluir el Id en los resultados? Entonces sería más fácil eliminar esos duplicados posteriormente. - user797717

@ user797717: necesitaría tener MIN (ID) y luego eliminar los valores de ID que no están en el último si los valores MIN (ID) - gbn

¿Qué pasa con los casos en los que alguna de las columnas tiene valores nulos? - Ankit Dhingra

Muchas gracias por esto, y sí, funciona en Oracle, aunque necesitaba la singularidad de la condición, así que en lugar de >1 =1 - Bill Naylor

prueba esto:

declare @YourTable table (id int, name varchar(10), email varchar(50))

INSERT @YourTable VALUES (1,'John','John-email')
INSERT @YourTable VALUES (2,'John','John-email')
INSERT @YourTable VALUES (3,'fred','John-email')
INSERT @YourTable VALUES (4,'fred','fred-email')
INSERT @YourTable VALUES (5,'sam','sam-email')
INSERT @YourTable VALUES (6,'sam','sam-email')

SELECT
    name,email, COUNT(*) AS CountOf
    FROM @YourTable
    GROUP BY name,email
    HAVING COUNT(*)>1

SALIDA:

name       email       CountOf
---------- ----------- -----------
John       John-email  2
sam        sam-email   2

(2 row(s) affected)

si quieres los ID de los dups usa esto:

SELECT
    y.id,y.name,y.email
    FROM @YourTable y
        INNER JOIN (SELECT
                        name,email, COUNT(*) AS CountOf
                        FROM @YourTable
                        GROUP BY name,email
                        HAVING COUNT(*)>1
                    ) dt ON y.name=dt.name AND y.email=dt.email

SALIDA:

id          name       email
----------- ---------- ------------
1           John       John-email
2           John       John-email
5           sam        sam-email
6           sam        sam-email

(4 row(s) affected)

para eliminar los duplicados intente:

DELETE d
    FROM @YourTable d
        INNER JOIN (SELECT
                        y.id,y.name,y.email,ROW_NUMBER() OVER(PARTITION BY y.name,y.email ORDER BY y.name,y.email,y.id) AS RowRank
                        FROM @YourTable y
                            INNER JOIN (SELECT
                                            name,email, COUNT(*) AS CountOf
                                            FROM @YourTable
                                            GROUP BY name,email
                                            HAVING COUNT(*)>1
                                        ) dt ON y.name=dt.name AND y.email=dt.email
                   ) dt2 ON d.id=dt2.id
        WHERE dt2.RowRank!=1
SELECT * FROM @YourTable

SALIDA:

id          name       email
----------- ---------- --------------
1           John       John-email
3           fred       John-email
4           fred       fred-email
5           sam        sam-email

(4 row(s) affected)

Respondido 10 Abr '18, 09:04

* Los nombres de las tablas distinguen entre mayúsculas y minúsculas (3) {[0] => string (5) "42000" [1] => int (1064) [2] => string (226) "Tiene un error en su sintaxis SQL; consulte el manual que corresponde a la versión de su servidor MySQL para conocer la sintaxis correcta para usar cerca de '(PARTITION BY y.employee_id, y.leave_type_id) AS RowRank' en la línea 1 "} - JAMZAD

Prueba esto:

SELECT name, email
FROM users
GROUP BY name, email
HAVING ( COUNT(*) > 1 )

Respondido 07 Abr '10, 19:04

Si desea eliminar los duplicados, aquí hay una forma mucho más sencilla de hacerlo que tener que buscar filas pares / impares en una sub-selección triple:

SELECT id, name, email 
FROM users u, users u2
WHERE u.name = u2.name AND u.email = u2.email AND u.id > u2.id

Y entonces para eliminar:

DELETE FROM users
WHERE id IN (
    SELECT id/*, name, email*/
    FROM users u, users u2
    WHERE u.name = u2.name AND u.email = u2.email AND u.id > u2.id
)

Mucho más fácil de leer y entender en mi humilde opinión

Nota: El único problema es que debe ejecutar la solicitud hasta que no se eliminen filas, ya que elimina solo 1 de cada duplicado cada vez

Respondido el 30 de diciembre de 16 a las 12:12

Agradable y fácil de leer; Sin embargo, me gustaría encontrar una manera de eliminar varias filas duplicadas de una sola vez. - Caña Dickon

Esto no funciona para mí, ya que tengo You can't specify target table 'users' for update in FROM clause - Gato blanco

@Whitecat parece un simple problema de MySQL: stackoverflow.com/questions/4429319/… - Tancrede Chazallet

Me falla. Recibo: "DBD :: CSV :: st falló la ejecución: uso del valor no inicializado $ _ [1] en el elemento hash en /Users/hornenj/perl5/perlbrew/perls/perl-5.26.0/lib/site_perl/5.26.0. 43 / SQL / Eval.pm línea XNUMX "- nigel horne

Creo que la cláusula donde debería ser "u.name = u2.name AND u.email = u2.email AND (u.id> u2.id OR u2.id> u.id)" ¿no es así? - daremtheboot

Intente lo siguiente:

SELECT * FROM
(
    SELECT Id, Name, Age, Comments, Row_Number() OVER(PARTITION BY Name, Age ORDER By Name)
        AS Rank 
        FROM Customers
) AS B WHERE Rank>1

Respondido el 12 de enero de 16 a las 10:01

Un ligero cambio a SELECT * me ayudó a resolver una búsqueda de una hora. Nunca antes había usado OVER (PARTITION BY. ¡Nunca dejo de sorprenderme de cuántas formas de hacer lo mismo en SQL! - joe ruder

 SELECT name, email 
    FROM users
    WHERE email in
    (SELECT email FROM users
    GROUP BY email 
    HAVING COUNT(*)>1)

Respondido 22 Jul 15, 08:07

Un poco tarde para la fiesta, pero encontré una solución realmente genial para encontrar todos los ID duplicados:

SELECT GROUP_CONCAT( id )
FROM users
GROUP BY email
HAVING ( COUNT(email) > 1 )

respondido 17 nov., 15:10

Parece ser una solución de azúcar sintáctica. Buen hallazgo. - Chef_Código

Tenga en cuenta que GROUP_CONCAT se detendrá después de una duración predeterminada, por lo que es posible que no obtenga todos los ids. - v010dya

prueba este código

WITH CTE AS

( SELECT Id, Name, Age, Comments, RN = ROW_NUMBER()OVER(PARTITION BY Name,Age ORDER BY ccn)
FROM ccnmaster )
select * from CTE 

Respondido el 30 de enero de 18 a las 08:01

Esto selecciona / elimina todos los registros duplicados excepto un registro de cada grupo de duplicados. Entonces, la eliminación deja todos los registros únicos + un registro de cada grupo de duplicados.

Seleccionar duplicados:

SELECT *
FROM table
WHERE
    id NOT IN (
        SELECT MIN(id)
        FROM table
        GROUP BY column1, column2
);

Eliminar duplicados:

DELETE FROM table
WHERE
    id NOT IN (
        SELECT MIN(id)
        FROM table
        GROUP BY column1, column2
);

Tenga en cuenta que hay una gran cantidad de registros, ya que puede causar problemas de rendimiento.

Respondido el 09 de enero de 18 a las 13:01

Error en la consulta de eliminación: no puede especificar las 'ciudades' de la tabla de destino para la actualización en la cláusula FROM - Alí Azhar

No hay 'ciudades' de tabla ni cláusula de actualización. ¿Qué quieres decir? ¿Dónde hay un error en la consulta de eliminación? - Martín Silovský

¿Qué significa "OP"? - Martín Silovský

En caso de trabajar con Oracle, sería preferible esta forma:

create table my_users(id number, name varchar2(100), email varchar2(100));

insert into my_users values (1, 'John', 'asd@asd.com');
insert into my_users values (2, 'Sam', 'asd@asd.com');
insert into my_users values (3, 'Tom', 'asd@asd.com');
insert into my_users values (4, 'Bob', 'bob@asd.com');
insert into my_users values (5, 'Tom', 'asd@asd.com');

commit;

select *
  from my_users
 where rowid not in (select min(rowid) from my_users group by name, email);

Respondido el 16 de junio de 14 a las 09:06

select name, email
, case 
when ROW_NUMBER () over (partition by name, email order by name) > 1 then 'Yes'
else 'No'
end "duplicated ?"
from users

Respondido el 08 de Septiembre de 16 a las 07:09

Las respuestas de solo código están mal vistas en Stack Overflow, ¿podría explicar por qué esto responde a la pregunta? - rico benner

@RichBenner: No encontré la respuesta como, todas y cada una de las filas en el resultado y que nos dice cuáles son filas duplicadas y cuáles no de un vistazo y que no debemos agrupar, porque si queremos combinar esto La consulta con cualquier otro grupo de consultas no es una buena opción. - Narendra

Agregar Id a la declaración de selección y filtrar en duplicado, le da la posibilidad de eliminar los identificadores duplicados y mantener cada uno. - Antoine Reinhold Bertrand

Si desea ver si hay filas duplicadas en su tabla, utilicé la siguiente Consulta:

create table my_table(id int, name varchar(100), email varchar(100));

insert into my_table values (1, 'shekh', 'shekh@rms.com');
insert into my_table values (1, 'shekh', 'shekh@rms.com');
insert into my_table values (2, 'Aman', 'aman@rms.com');
insert into my_table values (3, 'Tom', 'tom@rms.com');
insert into my_table values (4, 'Raj', 'raj@rms.com');


Select COUNT(1) As Total_Rows from my_table 
Select Count(1) As Distinct_Rows from ( Select Distinct * from my_table) abc 

Respondido 26 ago 14, 11:08

SELECT id, COUNT(id) FROM table1 GROUP BY id HAVING COUNT(id)>1;

Creo que esto funcionará correctamente para buscar valores repetidos en una columna en particular.

contestado el 08 de mayo de 15 a las 08:05

Esto no agrega nada a la respuesta principal, y técnicamente ni siquiera difiere realmente del código OP publicado en la pregunta. - Jeroen

select id,name,COUNT(*) from user group by Id,Name having COUNT(*)>1

Respondido el 08 de enero de 20 a las 18:01

 select emp.ename, emp.empno, dept.loc 
          from emp
 inner join dept 
          on dept.deptno=emp.deptno
 inner join
    (select ename, count(*) from
    emp
    group by ename, deptno
    having count(*) > 1)
 t on emp.ename=t.ename order by emp.ename
/

Respondido 15 Oct 14, 17:10

Esto es lo fácil que se me ocurrió. Utiliza una expresión de tabla común (CTE) y una ventana de partición (creo que estas características están en SQL 2008 y versiones posteriores).

Este ejemplo busca a todos los estudiantes con nombre y fecha de nacimiento duplicados. Los campos en los que desea verificar la duplicación van en la cláusula OVER. Puede incluir cualquier otro campo que desee en la proyección.

with cte (StudentId, Fname, LName, DOB, RowCnt)
as (
SELECT StudentId, FirstName, LastName, DateOfBirth as DOB, SUM(1) OVER (Partition By FirstName, LastName, DateOfBirth) as RowCnt
FROM tblStudent
)
SELECT * from CTE where RowCnt > 1
ORDER BY DOB, LName

Respondido 01 Jul 16, 20:07

¿Cómo podemos contar los valores duplicados? o se repite 2 veces o más de 2. solo cuéntelos, no en grupo.

tan simple como

select COUNT(distinct col_01) from Table_01

Respondido el 11 de diciembre de 14 a las 10:12

¿Cómo funcionaría esto para la pregunta que se formuló? Esto hace no proporcione filas que dupliquen información en varias columnas (por ejemplo, "correo electrónico" y "nombre") en diferentes filas. - Jeroen

Al usar CTE también podemos encontrar un valor duplicado como este

with MyCTE
as
(
select Name,EmailId,ROW_NUMBER() over(PARTITION BY EmailId order by id) as Duplicate from [Employees]

)
select * from MyCTE where Duplicate>1

Respondido el 26 de Septiembre de 16 a las 13:09

Esto también debería funcionar, tal vez inténtelo.

  Select * from Users a
            where EXISTS (Select * from Users b 
                where (     a.name = b.name 
                        OR  a.email = b.email)
                     and a.ID != b.id)

Especialmente bueno en su caso si busca duplicados que tengan algún tipo de prefijo o cambio general como, por ejemplo, un nuevo dominio en el correo. entonces puedes usar replace () en estas columnas

Respondido 15 Abr '16, 00:04

SELECT * FROM users u where rowid = (select max(rowid) from users u1 where
u.email=u1.email);

Respondido 22 Jul 16, 21:07

SELECT name, email,COUNT(email) 
FROM users 
WHERE email IN (
    SELECT email 
    FROM users 
    GROUP BY email 
    HAVING COUNT(email) > 1)

Respondido 17 Feb 20, 19:02

No puedes usar COUNT sin GROUP BY, a menos que se refiera a toda la tabla. - ralffriedl

Sin Group By, usaste COUNT pero aquí estoy cometiendo un error de escritura al escribir COUNT - Mohammad Neamul Islam

Lo más importante aquí es tener la función más rápida. También deben identificarse los índices de duplicados. La autounión es una buena opción, pero para tener una función más rápida, es mejor buscar primero las filas que tienen duplicados y luego unirse con la tabla original para encontrar la identificación de las filas duplicadas. Finalmente ordene por cualquier columna excepto id para tener filas duplicadas cerca una de la otra.

SELECT u.*
FROM users AS u
JOIN (SELECT username, email
      FROM users
      GROUP BY username, email
      HAVING COUNT(*)>1) AS w
ON u.username=w.username AND u.email=w.email
ORDER BY u.email;

contestado el 28 de mayo de 20 a las 21:05

Si desea buscar datos duplicados (por uno o varios criterios) y seleccione las filas reales.

with MYCTE as (
    SELECT DuplicateKey1
        ,DuplicateKey2 --optional
        ,count(*) X
    FROM MyTable
    group by DuplicateKey1, DuplicateKey2
    having count(*) > 1
) 
SELECT E.*
FROM MyTable E
JOIN MYCTE cte
ON E.DuplicateKey1=cte.DuplicateKey1
    AND E.DuplicateKey2=cte.DuplicateKey2
ORDER BY E.DuplicateKey1, E.DuplicateKey2, CreatedAt

http://developer.azurewebsites.net/2014/09/better-sql-group-by-find-duplicate-data/

Respondido el 01 de enero de 15 a las 14:01

Para eliminar registros cuyos nombres están duplicados

;WITH CTE AS    
(

    SELECT ROW_NUMBER() OVER (PARTITION BY name ORDER BY name) AS T FROM     @YourTable    
)

DELETE FROM CTE WHERE T > 1

Respondido el 10 de enero de 19 a las 15:01

¿Funciona? ¿Cómo es que obtengo este error 'la relación "cte" no existe' en Postgres? - newman

CTE también funciona en postgress sql. Aquí está el enlace postgresqltutorial.com/postgresql-cte Debe faltar algo más. - Alguacil

Para verificar desde un registro duplicado en una tabla.

select * from users s 
where rowid < any 
(select rowid from users k where s.name = k.name and s.email = k.email);

or

select * from users s 
where rowid not in 
(select max(rowid) from users k where s.name = k.name and s.email = k.email);

Eliminar el registro duplicado en una tabla.

delete from users s 
where rowid < any 
(select rowid from users k where s.name = k.name and s.email = k.email);

or

delete from users s 
where rowid not in 
(select max(rowid) from users k where s.name = k.name and s.email = k.email);

respondido 18 mar '19, 17:03

SELECT column_name,COUNT(*) FROM TABLE_NAME GROUP BY column1, HAVING COUNT(*) > 1;

Respondido el 11 de diciembre de 17 a las 13:12

Es posible que desee probar esto

SELECT NAME, EMAIL, COUNT(*)
FROM USERS
GROUP BY 1,2
HAVING COUNT(*) > 1

Respondido el 25 de junio de 19 a las 17:06

Otra forma fácil de probar esto usando la función analítica también:

SELECT * from 

(SELECT name, email,

COUNT(name) OVER (PARTITION BY name, email) cnt 

FROM users)

WHERE cnt >1;

respondido 19 nov., 20:15

te perdiste una coma después del correo electrónico :) - Amal PD

Podemos usar tener aquí que funcionan en funciones agregadas como se muestra a continuación

create table #TableB (id_account int, data int, [date] date)
insert into #TableB values (1 ,-50, '10/20/2018'),
(1, 20, '10/09/2018'),
(2 ,-900, '10/01/2018'),
(1 ,20, '09/25/2018'),
(1 ,-100, '08/01/2018')  

SELECT id_account , data, COUNT(*)
FROM #TableB
GROUP BY id_account , data
HAVING COUNT(id_account) > 1

drop table #TableB

Aquí como dos campos id_account y data se utilizan con Count (*). Por lo tanto, dará todos los registros que tengan más de una vez los mismos valores en ambas columnas.

Por alguna razón, erróneamente, no pudimos agregar ninguna restricción en la tabla del servidor SQL y los registros se insertaron duplicados en todas las columnas con la aplicación de front-end. Luego, podemos usar la siguiente consulta para eliminar la consulta duplicada de la tabla.

SELECT DISTINCT * INTO #TemNewTable FROM #OriginalTable
TRUNCATE TABLE #OriginalTable
INSERT INTO #OriginalTable SELECT * FROM #TemNewTable
DROP TABLE #TemNewTable

Aquí hemos tomado todos los registros distintos de la tabla original y eliminado los registros de la tabla original. Nuevamente insertamos todos los valores distintos de la nueva tabla en la tabla original y luego eliminamos la nueva tabla.

Respondido 26 Oct 18, 18:10

Puede utilizar la palabra clave SELECT DISTINCT para deshacerse de los duplicados. También puede filtrar por nombre y poner a todos los que tengan ese nombre en una tabla.

Respondido 04 Abr '19, 15:04

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.