RE: Regresar valores especificos

From: "Miguel Angel" <mvillagomez(at)sayab(dot)com(dot)mx>
To: <pgsql-es-ayuda(at)postgresql(dot)org>
Cc: <pgsql-es-ayuda(at)postgresql(dot)org>
Subject: RE: Regresar valores especificos
Date: 2006-03-09 19:48:28
Message-ID: 20060309194842.3E19C9DC99E@postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda


Bueno ya logré sacar la función, solo tuve que tomar los valores de las
tablas originales y aplicarles un CROSS JOIN:

CREATE OR REPLACE FUNCTION busca_similares() RETURNS SETOF RECORD AS $$
--Crea una tabla con los nombres similares dentro de con_0 a aquellos que no
fueron
-- localizados dentro de la tabla aux_0
DECLARE
a RECORD; --tabla origen
c RECORD; --tabla de comparacion
d RECORD; --tabla resultante
cont INTEGER;
nombre_sim VARCHAR;
BEGIN
FOR a IN (SELECT DISTINCT ON(clave) clave, nombre FROM aux_m WHERE listo<1)
LOOP
FOR cont IN 1..(SELECT LENGTH(a.nombre)::integer) LOOP
nombre_sim:=(SELECT (OVERLAY(a.nombre PLACING '%' FROM cont FOR
1))::varchar AS nombre FROM aux_m WHERE listo<1 AND clave=a.clave);

FOR c IN (SELECT con_id, nombre FROM (SELECT DISTINCT ON(con_id) con_id,
(((name || ' ')|| last_name || ' ')|| maiden_name)::varchar AS nombre FROM
con_0)AS Uno WHERE nombre LIKE nombre_sim) LOOP
FOR d IN (SELECT DISTINCT ON(con_id) clave::varchar, nombre1::varchar,
con_id::integer, nombres_similares::varchar FROM (SELECT DISTINCT ON(clave)
clave, (nombre)AS nombre1 FROM aux_m WHERE clave=a.clave AND
nombre=a.nombre)AS Dos CROSS JOIN (SELECT DISTINCT ON(con_id) con_id,
nombres_similares FROM (SELECT con_id, (((name || ' ')|| last_name || ' ')||
maiden_name)AS nombres_similares FROM con_0)AS Uno WHERE con_id=c.con_id AND
nombres_similares=c.nombre)AS Tres) LOOP
RETURN NEXT d;
END LOOP; --Selecciona el nombre de aux y el nombre similar de con_0 y
crea la nueva tabla resultante
END LOOP; -- toma la lista de nombres en con_0
END LOOP; -- cont para el largo de la palabra
END LOOP; --toma la lista de los no encontrados
RETURN;
END;
$$ LANGUAGE PLPGSQL;

SELECT * FROM busca_similares() AS( clave varchar, nombre1 varchar, con_id
integer, nombres_similares varchar);

Pero bueno, ahora solo me queda resolver el pequeño problemita del tiempo,
ya que esta consulta me tarda 1 hora con 40 minutos en resolver una lista de
1179 nombres.

Me podrían dar alguna sugerencia por favor.

-----Mensaje original-----
De: Miguel Angel [mailto:mvillagomez(at)sayab(dot)com(dot)mx]
Enviado el: Miércoles, 08 de Marzo de 2006 07:18 p.m.

Para: 'pgsql-es-ayuda(at)postgresql(dot)org'
Asunto: RV: Regresar valores especificos

Qué tal tengo un nuevo problema tengo en la BD una tabla que contiene esto:

CLAVES NOMBRES LISTO
1 NOMBRE1 0
2 NOMBRE2 0
3 NOMBRE3 0
4 NOMBRE4 0
5 NOMBRE5 0

Pero estos nombres son solo los que no coinciden por lo que estoy haciendo
una función que busque nombres similares. Así:

CREATE OR REPLACE FUNCTION busca_similares() RETURNS VOID AS $$
DECLARE
a RECORD;
nombre_sim RECORD;
c RECORD;
cont INTEGER;
BEGIN
FOR a IN (SELECT DISTINCT ON(clave) clave, nombre FROM aux_m WHERE listo<1)
LOOP
FOR cont IN 1..(SELECT LENGTH(a.nombre)) LOOP
nombre_sim:=(SELECT (OVERLAY(a.nombre PLACING '%' FROM cont FOR
1))::varchar AS nombre FROM aux_m WHERE listo<1 AND clave=a.clave);

FOR c IN (SELECT con_id, nombre FROM (SELECT DISTINCT ON(con_id) con_id,
(((name || ' ')|| last_name || ' ')|| maiden_name)::varchar AS nombre FROM
con_0)AS Uno WHERE nombre LIKE nombre_sim) LOOP
--REGRESAR a.clave, a.nombre, c.con_id, c.nombre
END LOOP; -- toma la lista de nombres en con_0
END LOOP; -- cont para el largo de la palabra
END LOOP; --toma la lista de los no encontrados
END;
$$ LANGUAGE PLPGSQL;

SELECT busca_similares();

Ok, dentro del primer for estoy almacenando la lista de los nombres de la
tabla1(aux_m) que no he podido localizar en la tabla2(con_0) para eso uso la
columna listo y si no se han encontrado siempre tendrá un valor de 0.

Dentro del segundo for es solo un contador que va desde 1 hasta el largo de
del nombre, esto es debido a que me muevo carácter a carácter por todo el
nombre que este dentro de a.nombre; en este for estoy usando la variable
nombre_sim en donde almaceno el nuevo nombre, por ejemplo este for sirva
para crear este tipo de nombres:

%OMBRE1
N%MBRE1
NO%BRE1
NOM%RE1
NOMB%E1
NOMBR%1
NOMBRE%

Uno por uno se almacena dentro de b.

Ok ya teniendo este "nombre similar" entro dentro del 3er for el cual me
trae una lista de todos los nombres parecidos que hay dentro de la
tabla2(con_0), para ello usa la instrucción en forma abreviada

SELECT con_id, nombre FROM con_0 WHERE nombre LIKE b(cada uno de los nombres
similares)

Asi este FOR me traería una lista de todos los nombres similares que hay
dentro de la tabla2(con_0), ahora lo único que debo hacer es guardar estos
resultados en una variable que almacene:

a.clave, a.nombre, c.con_id, c.nombre

Que sería la clave y nombre originales y el id y nombre similares
registrados en sistema.

Cada uno de estos registros los debo almacenar en una tabla por lo que
necesitaría usar el RETURN NEXT para que al final yo obtenga una tabla como
esta:

CLAVES NOMBRES ID NombresSimilares
1 NOMBRE1 10 NOMBRE_SIMILAR1
2 NOMBRE_SIMILAR2
2 NOMBRE2 3 NOMBRE_SIMILAR1
50 NOMBRE_SIMILAR2
100 NOMBRE_SIMILAR3
3 NOMBRE3 80 NOMBRE_SIMILAR1

Mi problema radica en que no se como indicarle a postgres que me cree la
tabla con fila con cada una de las columnas que le envío para formar la
tabla, en código(que se no servira) sería así:

FOR d IN (SELECT a.clave::varchar, a.nombre::varchar, c.con_id::integer,
c.nombre::varchar FROM a,c) LOOP
RETURN NEXT d;
END LOOP;

Y mandaría llamar a la función así:

SELECT * FROM busca_similares() AS( clave varchar, nombre_origen varchar,
con_id integer, nombre_similar varchar);

Pero me sale este error y no lo entiendo:

ERROR: cannot assign non-composite value to a record variable
CONTEXT: PL/pgSQL function "busca_similares" line 10 at assignment

Cómo puedo hacerle?

Responses

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message wilson soleto 2006-03-09 20:19:19 PostgreSQL y la RED
Previous Message Jaime Casanova 2006-03-09 18:07:19 Re: iniciacion