Postgres tuplas duplicadas

Bueno, estoy medio apurado así que voy al grano. Imaginen por ejemplo la tabla intersecciones de este post, pues anda todo muy bonito, pero tenemos el problema que se duplican las tuplas, por ejemplo:
geoprop2=# select * from intersecciones where idsegmentoscalle1 = 1 and idsegmentoscalle2 = 6167;
idsegmentoscalle1 | idsegmentoscalle2 | idregiones
-------------------+-------------------+------------
1 | 6167 |
(1 row)

geoprop2=# select * from intersecciones where idsegmentoscalle1 = 6167 and idsegmentoscalle2 = 1;
idsegmentoscalle1 | idsegmentoscalle2 | idregiones
-------------------+-------------------+------------
6167 | 1 |
(1 row)


Lo cual está, dentro de todo, bien ya que es cierto que la calle 1 se intersecciona con la calle 6167 y biceversa, pero se duplican los datos lo cual está mal, es por eso que voy a enseñarles un par de “trucos” para evitar esta redundancia.

Lo primero creamos una función:

CREATE OR REPLACE FUNCTION interexist(integer, integer) returns bool AS '
begin
PERFORM * from intersecciones where EXISTS(select 1 from intersecciones ini where idsegmentoscalle1=$2 and idsegmentoscalle2 = $1);
if found then return true;
else return false;
end if;
return true;
end;
' language 'plpgsql';

Esta función lo que hace es decirnos si hay una entrada igual, por ejemplo:

geoprop2=# select interexist(6167,19);
interexist
------------
f
(1 row)

geoprop2=# select interexist(6167,1);
interexist
------------
t
(1 row)

Entonces lo que nos está diciendo esta función es que la tupla {6167,1} ya tienen una tupla igual (o sea, la {1,6167}) y que la tupla {19,6167} no existe.

Con esto ya avanzamos bastante porque podemos eliminar los elementos duplicados con un delete:
geoprop2=# delete from intersecciones where interexist(idsegmentoscalle1,idsegmentoscalle2);

Recuerden que al usar exists en el select de nuestra función la consulta se correrá cada vez por lo que este delete es bastante lento.
Hacemos ahora la prueba:

geoprop2=# select * from intersecciones where idsegmentoscalle1 = 1 and idsegmentoscalle2 = 6167;
idsegmentoscalle1 | idsegmentoscalle2 | idregiones
-------------------+-------------------+------------
(0 rows)

geoprop2=# select * from intersecciones where idsegmentoscalle1 = 6167 and idsegmentoscalle2 = 1;
idsegmentoscalle1 | idsegmentoscalle2 | idregiones
-------------------+-------------------+------------
6167 | 1 |
(1 row)

Ahora solo nos falta que no se puedan agregar más entradas de este tipo:
geoprop2=# ALTER TABLE intersecciones ADD CONSTRAINT interseccion_duplicada CHECK (not interexist(idsegmentoscalle1,idsegmentoscalle2));
ALTER TABLE

!Y buala!, nos queda perfecto ;).
Espero que lo disfruten.

Comments are closed.