traer repetir repetidos registros mostrar menos eliminar duplicados consulta buscar agrupar sql sql-server database

repetir - sql eliminar registros duplicados menos uno



¿Cómo puedo eliminar filas duplicadas en una tabla? (13)

¿Puedes agregar un campo de identidad de clave principal a la tabla?

Tengo una mesa con decir 3 columnas. No hay una clave principal, por lo que puede haber filas duplicadas. Necesito solo guardar uno y borrar los otros. ¿Alguna idea de cómo hacer esto es Sql Server?


Agregue una columna de identidad para que actúe como una clave primaria sustituta y utilícela para identificar dos de las tres filas que se eliminarán.

Consideraría dejar la columna de identidad en su lugar después, o si esta es una especie de tabla de enlaces, cree una clave primaria compuesta en las otras columnas.


Aquí hay otra manera, con datos de prueba

create table #table1 (colWithDupes1 int, colWithDupes2 int) insert into #table1 (colWithDupes1, colWithDupes2) Select 1, 2 union all Select 1, 2 union all Select 2, 2 union all Select 3, 4 union all Select 3, 4 union all Select 3, 4 union all Select 4, 2 union all Select 4, 2 select * from #table1 set rowcount 1 select 1 while @@rowcount > 0 delete #table1 where 1 < (select count(*) from #table1 a2 where #table1.colWithDupes1 = a2.colWithDupes1 and #table1.colWithDupes2 = a2.colWithDupes2 ) set rowcount 0 select * from #table1


Después de limpiar el desorden actual, puede agregar una clave principal que incluya todos los campos de la tabla. eso evitará que te metas en el lío de nuevo. Por supuesto, esta solución podría romper el código existente. Eso tendrá que ser manejado también.


Esta es una situación difícil. Sin conocer su situación particular (tamaño de la tabla, etc.), creo que lo mejor que puede hacer es agregar una columna de identidad, rellenarla y luego eliminarla. Puede eliminar la columna más tarde, pero le sugiero que la guarde, ya que es realmente bueno tenerla en la mesa.


Manrico Corazzi: me especializo en Oracle, no en MS SQL, así que tendrás que decirme si esto es posible como un impulso en el rendimiento:

  1. Deje lo mismo que su primer paso: inserte valores distintos en la TABLA2 de TABLA1.
  2. Suelta TABLE1. (Drop debería ser más rápido que eliminar, supongo, tanto como truncar es más rápido que eliminar).
  3. Cambie el nombre de TABLE2 como TABLE1 (le ahorra tiempo, ya que cambia el nombre de un objeto en lugar de copiar datos de una tabla a otra).

No estoy seguro de si esto funciona con instrucciones DELETE, pero esta es una forma de encontrar filas duplicadas:

SELECT * FROM myTable t1, myTable t2 WHERE t1.field = t2.field AND t1.id > t2.id

No estoy seguro de si puede simplemente cambiar el "SELECCIONAR" a un "ELIMINAR" (¿alguien me quiere avisar?) , Pero incluso si no puede hacerlo, podría simplemente convertirlo en una subconsulta.


SELECCIONARÍA DISTINCT las filas y las arrojaría en una tabla temporal, luego soltaría la tabla fuente y volvería a copiar los datos de la temperatura. EDITAR: ahora con fragmento de código!

INSERT INTO TABLE_2 SELECT DISTINCT * FROM TABLE_1 GO DELETE FROM TABLE_1 GO INSERT INTO TABLE_1 SELECT * FROM TABLE_2 GO


Esta es una forma de hacerlo con Common Table Expressions, CTE. No implica bucles, ni columnas nuevas ni nada, y no hará que se desencadenen disparadores no deseados (debido a eliminaciones + inserciones).

Inspirado por este artículo .

CREATE TABLE #temp (i INT) INSERT INTO #temp VALUES (1) INSERT INTO #temp VALUES (1) INSERT INTO #temp VALUES (2) INSERT INTO #temp VALUES (3) INSERT INTO #temp VALUES (3) INSERT INTO #temp VALUES (4) SELECT * FROM #temp ; WITH [#temp+rowid] AS (SELECT ROW_NUMBER() OVER (ORDER BY i ASC) AS ROWID, * FROM #temp) DELETE FROM [#temp+rowid] WHERE rowid IN (SELECT MIN(rowid) FROM [#temp+rowid] GROUP BY i HAVING COUNT(*) > 1) SELECT * FROM #temp DROP TABLE #temp


¿Qué pasa con esta solución?

Primero ejecutas la siguiente consulta:

select ''set rowcount '' + convert(varchar,COUNT(*)-1) + '' delete from MyTable where field='''''' + field +'''''''' + '' set rowcount 0'' from mytable group by field having COUNT(*)>1

Y luego solo tienes que ejecutar el conjunto de resultados devuelto

set rowcount 3 delete from Mytable where field=''foo'' set rowcount 0 .... .... set rowcount 5 delete from Mytable where field=''bar'' set rowcount 0

He manejado el caso cuando solo tiene una columna, pero es bastante fácil adaptar el mismo enfoque antes de una columna. Avísame si quieres que publique el código.


El siguiente ejemplo funciona también cuando su PK es solo un subconjunto de todas las columnas de la tabla.

(Nota: Me gusta el enfoque con la inserción de otra columna de identificación sustituta más. Pero tal vez esta solución también sea útil).

Primero encuentra las filas duplicadas:

SELECT col1, col2, count(*) FROM t1 GROUP BY col1, col2 HAVING count(*) > 1

Si solo hay unos pocos, puede eliminarlos manualmente:

set rowcount 1 delete from t1 where col1=1 and col2=1

El valor de "rowcount" debe ser n-1 veces el número de duplicados. En este ejemplo, hay 2 puntos embotados, por lo tanto, el recuento de filas es 1. Si obtiene varias filas duplicadas, debe hacer esto para cada clave primaria única.

Si tiene muchos duplicados, copie cada clave una vez en otra tabla:

SELECT col1, col2, col3=count(*) INTO holdkey FROM t1 GROUP BY col1, col2 HAVING count(*) > 1

Luego copie las claves, pero elimine las duplicadas.

SELECT DISTINCT t1.* INTO holddups FROM t1, holdkey WHERE t1.col1 = holdkey.col1 AND t1.col2 = holdkey.col2

En tus llaves tienes ahora llaves únicas. Verifica si no obtienes ningún resultado:

SELECT col1, col2, count(*) FROM holddups GROUP BY col1, col2

Eliminar los duplicados de la tabla original:

DELETE t1 FROM t1, holdkey WHERE t1.col1 = holdkey.col1 AND t1.col2 = holdkey.col2

Inserta las filas originales:

INSERT t1 SELECT * FROM holddups

Por cierto y para ser completo: en Oracle hay un campo oculto que podrías usar (rowid):

DELETE FROM our_table WHERE rowid not in (SELECT MIN(rowid) FROM our_table GROUP BY column1, column2, column3... ;

ver: sitio de Microsoft Knowledge


Qué tal si:

select distinct * into #t from duplicates_tbl truncate duplicates_tbl insert duplicates_tbl select * from #t drop table #t


Este es el método que utilicé cuando hice esta pregunta :

DELETE MyTable FROM MyTable LEFT OUTER JOIN ( SELECT MIN(RowId) as RowId, Col1, Col2, Col3 FROM MyTable GROUP BY Col1, Col2, Col3 ) as KeepRows ON MyTable.RowId = KeepRows.RowId WHERE KeepRows.RowId IS NULL