2008-10-28 20 views
5

El tipo de base de datos es PostGres 8.3.Eliminar duplicados de una tabla

si escribía:

SELECT field1, field2, field3, count(*) 
FROM table1 
GROUP BY field1, field2, field3 having count(*) > 1; 

Tengo algunas filas que tienen un recuento de más de 1. ¿Cómo puedo sacar el duplicado (yo todavía quiero 1 fila para cada uno de ellos en lugar de 1 fila. .. yo no quiero eliminarlos todos)

Ejemplo:.

1-2-3 
1-2-3 
1-2-3 
2-3-4 
4-5-6 

debe convertirse en:

1-2-3 
2-3-4 
4-5-6 

La única respuesta que encontré es there, pero me pregunto si podría hacerlo sin la columna hash.

Advertencia que no tienen una PK con un número único de lo que no puede utilizar la técnica de minutos (...). El PK es los 3 campos.

+0

No estoy seguro de si lo entiendo bien. Usted dice "El PK es los 3 campos" - entonces, ¿por qué tiene duplicados en la tabla como múltiples registros 1-2-3? Corrígeme si estoy equivocado. –

+0

El PK estaba en los 3 campos, tuvimos que eliminarlos para una fusión (larga historia) ahora tenemos que volver a ponerlo. Tenemos algunos duplicados que nos gustaría quitar. –

Respuesta

6

Esta es una de las muchas razones por las que todas las tablas deben tener una clave principal (no necesariamente un ID o IDENTIDAD, sino una combinación de una o más columnas que identifiquen una fila única y su singularidad se aplique en la base de datos) .

Su mejor apuesta es algo como esto:

SELECT field1, field2, field3, count(*) 
INTO temp_table1 
FROM table1 
GROUP BY field1, field2, field3 having count(*) > 1 

DELETE T1 
FROM table1 T1 
INNER JOIN (SELECT field1, field2, field3 
     FROM table1 
     GROUP BY field1, field2, field3 having count(*) > 1) SQ ON 
      SQ.field1 = T1.field1 AND 
      SQ.field2 = T1.field2 AND 
      SQ.field3 = T1.field3 

INSERT INTO table1 (field1, field2, field3) 
SELECT field1, field2, field3 
FROM temp_table1 

DROP TABLE temp_table1 
+0

Actualmente estoy intentando su sugerencia. +1 –

+0

Funciona a pesar de que he modificado algunas cosas, como DELETE T1 no funciona, tuve que poner el T1 después de FROM table1 como T1. Pocas cosas así. Pero la solución fue rápida y exitosa aquí. –

+0

Me alegro de que funcionó para usted. Gracias por señalar mi vista del alias T1. Lo he corregido en el guión. –

0

Una respuesta posible es:

CREATE <temporary table> (<correct structure for table being cleaned>); 
BEGIN WORK; -- if needed 
INSERT INTO <temporary table> SELECT DISTINCT * FROM <source table>; 
DELETE FROM <source table> 
INSERT INTO <source table> SELECT * FROM <temporary table>; 
COMMIT WORK; -- needed 
DROP <temporary table>; 

No estoy seguro de si es necesaria la 'trabajo' en los estados de transacción, ni si lo explícito comenzar es necesario en PostgreSQL. Pero el concepto se aplica a cualquier DBMS.

Lo único que se debe tener en cuenta son las restricciones referenciales y, en particular, las operaciones de eliminación activadas. Si existen, esto puede resultar menos satisfactorio.

0

para ello se utiliza el ID de OID objeto (si la tabla se creó con él):

DELETE FROM table1 
WHERE OID NOT IN (SELECT MIN (OID) 
           FROM table1 
          GROUP BY field1, field2, field3) 
0

También debería malinterpretar algo, pero Diré:

SELECCIONE DISTINCT campo1, campo2, campo3 DESDE la tabla1

¿Demasiado fácil para ser bueno? ^^

+0

Creo que Daok quiere borrar todas menos una de las entradas duplicadas. –

0

El uso de TSQL, ni idea de si Postgres soporta tablas temporales, pero se podía seleccionar en una tabla temporal, y luego a través del bucle y borrar e insertar los resultados de nuevo en el original

-- **Disclaimer** using TSQL 
-- You could select your records into a temp table with a pk 
Create Table #dupes 
([id] int not null identity(1,1), f1 int, f2 int, f3 int) 

Insert Into #dupes (f1,f2,f3) values (1,2,3) 
Insert Into #dupes (f1,f2,f3) values (1,2,3) 
Insert Into #dupes (f1,f2,f3) values (1,2,3) 
Insert Into #dupes (f1,f2,f3) values (2,3,4) 
Insert Into #dupes (f1,f2,f3) values (4,5,6) 
Insert Into #dupes (f1,f2,f3) values (4,5,6) 
Insert Into #dupes (f1,f2,f3) values (4,5,6) 
Insert Into #dupes (f1,f2,f3) values (7,8,9) 

Select f1,f2,f3 From #dupes 

Declare @rowCount int 
Declare @counter int 
Set @counter = 1 
Set @rowCount = (Select Count([id]) from #dupes) 

while (@counter < @rowCount + 1) 
    Begin 
     Delete From #dupes 
     Where [Id] <> 
      (Select [id] From #dupes where [id][email protected]) 
       and 
      (
       [f1] = (Select [f1] from #dupes where [id][email protected]) 
       and 
       [f2] = (Select [f2] from #dupes where [id][email protected]) 
       and 
       [f3] = (Select [f3] from #dupes where [id][email protected]) 
      ) 
     Set @counter = @counter + 1 
    End 

Select f1,f2,f3 From #dupes -- You could take these results and pump them back into --your original table 

Drop Table #dupes 

probado esto en EM SQL Server 2000. No está familiarizado con las opciones de Postgres, pero tal vez esto lo lleve en la dirección correcta.

0

Este es el método más simple que he encontrado: sintaxis

PostgreSQL SQL:

CREATE TABLE tmp AS SELECT distinct * FROM table1 
truncate table table1 
insert into table1 select * from tmp 
drop table tmp 

sintaxis de T-SQL:

select distinct * into #tmp from table1 
truncate table table1 
insert into table1 select * from #tmp 
drop table #tmp 
+0

Truncar no funcionará si hay restricciones de clave externa – kd7

+0

correctas, suelte y vuelva a agregar restricciones después del truncamiento –

0

Un buen Answer para este problema, pero para Servidor SQL. Utiliza el ROWCOUNT que SQL Server ofrece, con buenos resultados. Nunca utilicé PostgreSQL y, por lo tanto, no conozco el equivalente de ROWCOUNT en PostgreSQL.

Cuestiones relacionadas