Zas! Por un error de programación, de repente aparecieron un montón de registros duplicados, y cuando digo un montón, son un montón!!!
y ahora? pues, a pensar con cabeza fría... cuáles son las opciones?
- borrar todos los duplicados a través del mismo sistema
- pensar en un script en cualquier lenguaje que haga todo de un sólo halón
Por razones de seguridad de los datos, me inclino por la segunda opción... lo primero que pensé es en cómo se podía hacer con SQL
La tabla:
\d centro_poblado Tabla «public.centro_poblado»Columna | Tipo | Modificadores ---------+-----------------------+-------------------------------------------------------------reg_001 | character varying(2) | not nullest_001 | character varying(2) | not nullmun_001 | character varying(2) | not nullpar_001 | character varying(2) | not nullcpo_001 | character varying(3) | not nullcpo_002 | character varying(50) | not nullid | integer | not null default nextval('centro_poblado_id_seq'::regclass)Como la tabla tiene un id de tipo serial, eso ayuda.
Verficiar cuáles son los registros repetidos:
SELECT COUNT(*), reg_001, est_001, mun_001, par_001 FROM centro_poblado GROUP BY cpo_002, reg_001, est_001, mun_001, par_001 ORDER BY reg_001, est_001, mun_001, par_001;Verificar los registros repetidos:
SELECT * FROM centro_poblado WHERE reg_001 = '06' AND est_001 = '14' AND mun_001 = '01' AND par_001 = '05';Contar los registros repetidos, en detalle:
SELECT count(*) FROM centro_poblado WHERE reg_001 = '06' AND est_001 = '14' AND mun_001 = '01' AND par_001 = '05' AND cpo_001 = '018';Verificar el id min y máx del detalle de los registros repetidos:
SELECT min(id), max(id) FROM centro_poblado WHERE reg_001 = '06' AND est_001 = '14' AND mun_001 = '01' AND par_001 = '05' AND cpo_001 = '018';La verdad es que luego descubrí que se podía hacer así:
SELECT * FROM centro_poblado AS a
WHERE EXISTS(
SELECT cpo_001, COUNT(cpo_001)
FROM centro_poblado
WHERE a.cpo_001= cpo_001
GROUP BY cpo_001
HAVING COUNT(cpo_001)>1)
ORDER BY cpo_001Eliminar los registros repetidos, menos 1:
DELETE FROM centro_poblado WHERE reg_001 = '06' AND est_001 = '14' AND mun_001 = '01' AND par_001 = '05' AND cpo_001 = '018' AND id > 1;Esto también se puede resolver con una tabla temporal, y metiendo la consulta en una función y todo eso, pero aun no lo he probado...
Finalmente, y gracias a la lista de usuarios de postgres y su histórico, me encontré [1]:
DELETE FROM centro_poblado WHERE ctid NOT IN (SELECT min(ctid) FROM centro_poblado GROUP BY cpo_002, reg_001, est_001, mun_001, par_001);
[1]http://archives.postgresql.org/pgsql-es-ayuda/2007-01/msg00353.php