Posteado por: alfayate | agosto 5, 2010

Trucos Oracle: Comparación de cadenas similares por proximidad

Problema: Necesitamos comparar cadenas que sean “aproximadamente” iguales, o sea que aunque no sean exactamente iguales, se parezcan mucho. Esto es relativamente frecuente en datos como los nombres de personas y lugares extranjeros o en otro idioma, que pueden haberse introducido de forma muy distinta dependiendo del criterio empleado (o como Dios le dé a entender a la persona correspondiente). Tradicionalmente esto se trata quitando espacios y acentos (y apóstrofes), poniendo todo a minúsculas o mayúsculas, con comodines, etc… pero todo esto resulta de escasa utilidad cuando las consonantes bailan de sitio, aparecen o desaparecen, se intercambian las vocales, etc…

Un recurso común en Oracle es usar la función soundex, que a partir de una cadena devuelve el valor fonético de la misma (la primera letra más tres números); no tiene en cuenta las vocales y toma sólo las cinco primeras consonantes para calcular el resultado. Desgraciadamente no siempre obtiene la precisión necesaria para distinguir entre las cadenas que deben ser consideradas similares de las que no.

Si en nuestro caso necesitamos algo más, podemos emplear el paquete utl_match, que, ojo, sólo está disponible a partir de la versión 10g release 2 de Oracle. Este paquete dispone de varias funciones para el propósito que nos ocupa, pero, a mi entender, la más interesante es edit_distance_similarity, que calcula el porcentaje de similitud de las cadenas que comparamos. La forma de usarla sería:

utl_match.edit_distance_similarity(cad1,cad2) > 60

Esto es una condición que evalúa a verdadero si el porcentaje de similitud de las cadenas es mayor que el 60%. Por las pruebas que he hecho, éste sería un buen valor para determinar si dos cadenas son aproximadamente iguales, aunque, como siempre, lo ideal sería usarlo como punto de partida y luego hacer pruebas con los datos concretos de nuestro problema, para ir ajustando.

Un par de avisos para terminar: el primero que ninguna de las dos cadenas puede ser null, con lo que si no podemos asegurar esto, lo mejor es usar nvl. Esta función comprueba si un valor es nulo, y si lo es, en vez de null devuelve un valor que le pasemos p.e. nvl(cad,”ES_NULO”). El segundo es que para “ponérselo más fácil” a la función, podemos de mano quitar los espacios en blanco y poner todas las letras a minúsculas previamente (si la capitalización de las letras nos es indiferente), tal que así:

utl_match.edit_distance_similarity(lower(trim(cad1)),lower(trim(cad2))) > 60

Anuncios

Responses

  1. Se pueden usar indices con utl_match.edit_distance_similarity ?

    • Hola GuillermoTI.

      No veo por qué no. La función se limita a comparar cadenas, pero no te lo podría asegurar tajantemente. Lo mejor es que hagas tú mismo la prueba con alguna tabla donde haya un campo o dos alfanuméricos que sean índices.


Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Categorías

A %d blogueros les gusta esto: