Pregunta Encontrar valores duplicados en una tabla SQL


Es fácil de encontrar duplicates 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, entonces necesito encontrar ellos primero.


1297
2018-04-07 18:17


origen


Respuestas:


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

Simplemente agrupe en ambas columnas.

Nota: el estándar anterior de ANSI 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 desde 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:


2121
2018-04-07 18:20



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 quiere los ID de los dups, use 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 prueba:

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)

273
2018-04-07 18:22



Prueba esto:

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

89
2018-04-07 18:20



Si desea eliminar los duplicados, esta es una forma mucho más sencilla de hacerlo que tener que buscar filas pares / impares en una triple selección secundaria:

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 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 haya filas eliminadas, ya que solo elimina 1 de cada duplicado cada vez


42
2018-03-14 14:22



Pruebe 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

30
2017-12-31 10:07



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

21
2017-07-22 07:12



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

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

17
2017-11-17 10:21