2012-02-22 82 views
5

Estoy queriendo saber si hay una manera, en Oracle SQL, de comparar dos cadenas para semejanzas con excepción de = o like. Por ejemplo, SQL Server tiene una función difference(str1, str2) que compara las dos cadenas y da una clasificación de similitud (0 a 4). No es exactamente lo que quiero pero eso aún sería extremadamente útil.Comparaciones avanzadas de cadenas en Oracle SQL

que estaba esperando específicamente para funciones o métodos eso:

  1. comparar una cadena de caracteres por el carácter (devolver el número de coincidencias exactas)
  2. saber cuántos caracteres hay en una cadena, pero en el lugar equivocado

El uso principal sería para cadenas de la misma longitud, que contienen números (ID, números de teléfono, etc.) Para mis propósitos, lo usaría para buscar posibles coincidencias en las que l etters/numbers pueden haber sido transpuestos. Soundex(string) funciona bien para cadenas alfa, pero parece ignorar los números (por una buena razón).

No tengo privilegios para crear funciones por mi cuenta, pero si alguien conoce un método para hacerlo yo estaría interesado en escucharlo. Una solución para comparar char-a-char (que sólo funciona si se conoce el número máximo de caracteres) es:

--For char-to-char counts 
    Decode(substr(ID1,1,1), substr(ID2,1,1), 1, 0) + 
    Decode(substr(ID1,2,1), substr(ID2,2,1), 1, 0) + 
    [...] 
    Decode(substr(ID1,N,1), substr(ID2,N,1), 1, 0) 

Pero eso es casi tan poco elegante como usted puede conseguir.

Cualquier ayuda sería muy apreciada.

+0

posible duplicado de [Búsqueda de las mejores coincidencias para un valor de cadena - Oracle/Java] (http://stackoverflow.com/questions/8068162/finding-best-matches-for-a-string-value-oracle-java) –

Respuesta

20

Parece que usted está buscando la UTL_MATCH package

SELECT utl_match.edit_distance(string1, string2) 
    FROM dual 

le indica el número de ediciones necesario para transformar en cadena1 cadena2

SQL> select utl_match.edit_distance('Bear', 'berry') from dual; 

UTL_MATCH.EDIT_DISTANCE('BEAR','BERRY') 
--------------------------------------- 
             3 

También hay un par de funciones de similitud y EDIT_DISTANCE_SIMILARITYJARO_WINKLER_SIMILARITY que dan puntajes de similitud entre 0 y 100 que te dan una idea de cuán similares son las cuerdas.

+0

Esto es asombroso. ¡Estoy muy entusiasmado con las posibilidades con estos conjuntos de funciones! Esto es mucho mejor de lo que esperaba, muchas gracias por su publicación. – Phillip

+0

No estoy seguro de si esto es igual o diferente a la función Ld(). Creo que Ld significa la diferencia de Levenschtein. – jinglesthula

+0

@jinglesthula - La función 'edit_distance' utiliza el algoritmo de distancia de Levenshtein. No estoy seguro de la función 'Ld' de ese idioma al que se refiere, esa no es una función que forma parte de una base de datos de instalación, así que no estoy seguro de si es la misma cosa. Tal vez alguien en su organización creó una función 'LD' que llama' utl_match.edit_distance'? O tal vez reimplementaron el algoritmo. –

1

Hay varias maneras de resolver esto en Oracle:

  1. Puede crear un procedimiento almacenado.

  2. Puede cargar el código Java en una base de datos Oracle y usar las funciones definidas en el código (intro).

  3. Puede buscar las cadenas de la base de datos y compararlas en su aplicación.

ventajas/desventajas:

procedimientos tiendas son algo difícil de escribir y mantener y que podría ser lento. Pero son una herramienta estándar, de uso frecuente, por lo que a menos que su empresa tenga una política estricta de "no intervención", suelen ser la "solución" (a menudo como la expresión regular que resuelve un problema y crea dos nuevos).

El código de Java es una herramienta extremadamente poderosa, pero he visto muchas instalaciones de Oracle y hasta ahora nadie usó el código de Java. No estoy seguro de cuáles son las razones, muchas personas parecen recelar, pero nunca se materializó nada sólido. También tenga en cuenta que los servidores DB están optimizados para IO y menos para la CPU. El código Java tan complejo puede arruinar su rendimiento en más formas de las que cabría esperar (siguiendo las líneas de "muchos son cautelosos")

La última solución siempre funciona, pero dependiendo de lo que necesite, podría no ser una opción. Por otro lado, he visto código que realizó mucho mejor al descargar una gran cantidad de datos y realizar el complejo proceso en la aplicación. En un ejemplo, la consulta tomaría 15 segundos y la descarga + línea de comando grep(1) tomó 0.3s.