solo repetidos registros registro eliminar duplicados duplicado duplicadas dejando cómo consulta como claves borrar sql postgresql duplicates netezza

repetidos - eliminar registros duplicados sql server 2008 r2



Cómo eliminar filas duplicadas sin identificador único (10)

Tengo filas duplicadas en mi tabla y quiero eliminar duplicados de la manera más eficiente ya que la tabla es grande. Después de algunas investigaciones, he llegado a esta consulta:

WITH TempEmp AS ( SELECT name, ROW_NUMBER() OVER(PARTITION by name, address, zipcode ORDER BY name) AS duplicateRecCount FROM mytable ) -- Now Delete Duplicate Records DELETE FROM TempEmp WHERE duplicateRecCount > 1;

Pero solo funciona en SQL, no en Netezza. Parece que no le gusta el DELETE después de la cláusula WITH ?


Daré una solución simple. Primero, copie una fila (Para copiar esa fila, haga clic en la columna generada sql). Ahora elimine todas las filas que dupliquen. Ahora, abra la opción de edición de 200 filas del servidor sql y luego pegue la fila que haya copiado anteriormente.


De la documentación, eliminar filas duplicadas

Una pregunta frecuente en el IRC es cómo eliminar las filas que están duplicadas en un conjunto de columnas, manteniendo solo el que tiene la ID más baja. Esta consulta lo hace para todas las filas de tablename que tengan la misma columna1, columna2 y columna3.

DELETE FROM tablename WHERE id IN (SELECT id FROM (SELECT id, ROW_NUMBER() OVER (partition BY column1, column2, column3 ORDER BY id) AS rnum FROM tablename) t WHERE t.rnum > 1);

A veces se usa un campo de marca de tiempo en lugar de un campo de ID.


En un mundo perfecto, cada mesa tiene un identificador único de algún tipo.
En ausencia de una columna única (o una combinación de ctid ), use la columna ctid :

DELETE FROM tbl WHERE ctid NOT IN ( SELECT min(ctid) -- ctid is NOT NULL by definition FROM tbl GROUP BY name, address, zipcode); -- list columns defining duplicates

La consulta anterior es corta, listando convenientemente los nombres de las columnas solo una vez. NOT IN (SELECT ...) es un estilo de consulta complicado cuando los valores NULL pueden estar involucrados, pero la columna del sistema ctid nunca es NULL. Ver:

Usar EXISTS como lo demuestra @Gordon es típicamente más rápido. Entonces, es una auto-unión con la cláusula USING como @isapir añadida más tarde . Ambos deberían dar como resultado el mismo plan de consulta.

Pero tenga en cuenta una diferencia importante : estas otras consultas tratan los valores NULL como no iguales , mientras que GROUP BY (o DISTINCT o DISTINCT ON () ) tratan los valores NULL como iguales. No importa si las columnas clave están definidas NOT NULL . De lo contrario, dependiendo de tu definición de "duplicado", necesitarás uno o el otro enfoque. O utilice IS NOT DISTINCT FROM en comparación de los valores (que pueden no ser capaces de usar algunos índices).

Renuncia:

ctid es un detalle de implementación interna de Postgres, no está en el estándar SQL y se puede cambiar entre versiones principales sin previo aviso (incluso si eso es muy poco probable). Sus valores pueden cambiar entre comandos debido a procesos en segundo plano o operaciones de escritura simultáneas (pero no dentro del mismo comando).

Relacionado:

Aparte:

El objetivo de una declaración DELETE no puede ser el CTE, solo la tabla subyacente. Eso es un derrame de SQL Server, como es todo su enfoque.


Esto es lo que se me ocurrió, usando un group by

DELETE FROM mytable WHERE id NOT in ( SELECT MIN(id) FROM mytable GROUP BY name, address, zipcode )

Elimina los duplicados, preservando el registro más antiguo que tiene duplicados.


La sintaxis válida se especifica en http://www.postgresql.org/docs/current/static/sql-delete.html

ALTERARía su tabla para agregar una identificación de clave primaria de autoincrementación única para que pueda ejecutar una consulta como la siguiente, que mantendrá el primero de cada conjunto de duplicados (es decir, el que tiene la identificación más baja). Tenga en cuenta que agregar la clave es un poco más complicado en Postgres que en otros DB.

DELETE FROM mytable d USING ( SELECT min(id), name, address, zip FROM mytable GROUP BY name, address, zip HAVING COUNT() > 1 ) AS k WHERE d.id <> k.id AND d.name=k.name AND d.address=k.address AND d.zip=k.zip;


Me gusta la solución de @ erwin-brandstetter, pero quería mostrar una solución con la palabra clave USING :

DELETE FROM table_with_dups T1 USING table_with_dups T2 WHERE T1.ctid < T2.ctid -- delete the "older" ones AND T1.name = T2.name -- list columns that define duplicates AND T1.address = T2.address AND T1.zipcode = T2.zipcode;

Si desea revisar los registros antes de eliminarlos, simplemente reemplace DELETE con SELECT * y USING con una coma,, es decir,

SELECT * FROM table_with_dups T1 , table_with_dups T2 WHERE T1.ctid < T2.ctid -- select the "older" ones AND T1.name = T2.name -- list columns that define duplicates AND T1.address = T2.address AND T1.zipcode = T2.zipcode;

Actualización: Probé algunas de las diferentes soluciones aquí para la velocidad. Si no espera muchos duplicados, esta solución funciona mucho mejor que los que tienen una cláusula NOT IN (...) ya que generan muchas filas en la subconsulta.

Si reescribe la consulta para usar IN (...) entonces se realiza de manera similar a la solución presentada aquí, pero el código SQL se vuelve mucho menos conciso.

Actualización 2: si tiene valores NULL en una de las columnas clave (que realmente no debería IMO), puede usar COALESCE() en la condición para esa columna, por ejemplo

AND COALESCE(T1.col_with_nulls, ''[NULL]'') = COALESCE(T2.col_with_nulls, ''[NULL]'')


Podemos usar una función de ventana para la eliminación muy efectiva de las filas duplicadas:

DELETE FROM tab WHERE id IN (SELECT id FROM (SELECT row_number() OVER (PARTITION BY column_with_duplicate_values), id FROM tab) x WHERE x.row_number > 1);

La versión optimizada de algunos PostgreSQL (con ctid):

DELETE FROM tab WHERE ctid = ANY(ARRAY(SELECT ctid FROM (SELECT row_number() OVER (PARTITION BY column_with_duplicate_values), ctid FROM tab) x WHERE x.row_number > 1));


Si desea mantener una fila fuera de las filas duplicadas en la tabla.

create table some_name_for_new_table as (select * from (select *,row_number() over (partition by pk_id) row_n from your_table_name_where_duplicates_are_present) a where row_n = 1);

Esto creará una tabla que puedes copiar.

Antes de copiar la tabla, elimine la columna ''row_n''


Si desea un identificador único para cada fila, puede agregar uno (una serie o un guid) y tratarlo como una clave sustituta .

CREATE TABLE thenames ( name text not null , address text not null , zipcode text not null ); INSERT INTO thenames(name,address,zipcode) VALUES (''James'', ''main street'', ''123'' ) ,(''James'', ''main street'', ''123'' ) ,(''James'', ''void street'', ''456'') ,(''Alice'', ''union square'' , ''123'') ; SELECT*FROM thenames;

-- add a surrogate key ALTER TABLE thenames ADD COLUMN seq serial NOT NULL PRIMARY KEY ; SELECT*FROM thenames; DELETE FROM thenames del WHERE EXISTS( SELECT*FROM thenames x WHERE x.name=del.name AND x.address=del.address AND x.zipcode=del.zipcode AND x.seq < del.seq ); -- add the unique constrain,so that new dupplicates cannot be created in the future ALTER TABLE thenames ADD UNIQUE (name,address,zipcode) ; SELECT*FROM thenames;


Si no tiene otro identificador único, puede usar ctid :

delete from mytable where exists (select 1 from mytable t2 where t2.name = mytable.name and t2.address = mytable.address and t2.zip = mytable.zip and t2.ctid > mytable.ctid );

Es una buena idea tener una identificación única de auto incremento en cada mesa. Hacer una delete como esta es una razón importante por la cual.