sql >> Base de Datos >  >> RDS >> Mysql

Comparación de patrones con mysql entre dos columnas de tablas

Dos preguntas:¿las descripciones son estándar (las descripciones no cambian) o las ingresa un usuario? Si son estándar, agregue una columna que sea un número entero y haga una comparación en esta columna.

Si lo ingresa el usuario, su trabajo es más complicado porque está buscando algo que sea una búsqueda más difusa. Usé un algoritmo de búsqueda de bigramas para clasificar la similitud entre dos cadenas, pero esto no se puede hacer directamente en mySQL.

En lugar de una búsqueda difusa, puede usar LIKE, pero su eficiencia se limita a hacer un escaneo de tablas si termina poniendo el '%' al principio del término de búsqueda. Además, implica que puede obtener una coincidencia en la parte de la subcadena que elija, lo que significa que necesitaría conocer la subcadena con anticipación.

Estaré feliz de dar más detalles una vez que sepa lo que estás tratando de hacer.

EDIT1:Ok, dada su elaboración, deberá realizar una búsqueda de estilo difuso como mencioné. Utilizo un método de bigrama, que consiste en tomar cada entrada realizada por el usuario y dividirla en fragmentos de 2 o 3 caracteres. Luego almaceno cada uno de estos fragmentos en otra tabla con cada entrada clave de vuelta a la descripción real.

Ejemplo:

Descripción1:"Una carrera rápida hacia adelante"Descripción2:"Una carrera corta hacia adelante"

Si divide cada uno en 2 fragmentos de caracteres - 'A', 'f', 'fa', 'as', 'st'.....

Luego, puede comparar la cantidad de fragmentos de 2 caracteres que coinciden con ambas cadenas y obtener una "puntuación" que connotará precisión o similitud entre los dos.

Dado que no sé qué lenguaje de desarrollo está utilizando, dejaré la implementación, pero esto es algo que deberá hacerse no explícitamente en mySQL.

O la alternativa perezosa sería usar un servicio de búsqueda en la nube como el que tiene Amazon que proporcionará una búsqueda basada en los términos que le proporcione... Sin embargo, no estoy seguro de si le permiten agregar continuamente nuevas descripciones para considerar, y dependiendo de su aplicación, puede ser un poco costoso (en mi humilde opinión).

R

Para otra publicación de SO sobre la implementación de bigramas, vea esto SO bigrama/búsqueda difusa

--- Actualización por elaboración del interrogador---

En primer lugar, asumo que leyó la teoría en los enlaces que proporcioné... en segundo lugar, trataré de mantenerlo lo más independiente posible de la base de datos, ya que no necesita mySQL (aunque lo uso y funciona más que bien)

Bien, entonces el método bigram funciona bien para crear/comparar arreglos en memoria solo si las posibles coincidencias son relativamente pequeñas; de lo contrario, sufre un rendimiento de exploración de tabla como una tabla mysql sin índices con bastante rapidez. Por lo tanto, va a utilizar las fortalezas de la base de datos para ayudar a hacer la indexación por usted.

Lo que necesita es una tabla para contener los "términos" ingresados ​​​​por el usuario o el texto que desea comparar. La forma más simple es una tabla con dos columnas, una es un entero de incremento automático único que se indexará, llamaremos a hd_id a continuación, la segunda es un varchar (255) si las cadenas son bastante cortas, o TEXTO si pueden obtener largo - puede nombrar esto como quieras.

Luego, deberá crear otra tabla que tenga al menos TRES columnas:una para la columna de referencia de regreso a la columna de incremento automático de la otra tabla (llamaremos a este hd_id a continuación), la segunda sería un varchar() de diga 5 caracteres como máximo (esto contendrá sus fragmentos de bigrama) que llamaremos "bigrama" a continuación, y la tercera una columna de incremento automático llamada b_id a continuación. Esta tabla contendrá todos los bigramas para la entrada de cada usuario y se vinculará con la entrada general. Querrá indexar la columna varchar por sí misma (o primero en orden en un índice compuesto).

Ahora, cada vez que un usuario ingresa un término que desea buscar, debe ingresar el término en la primera tabla, luego dividir el término en bigramas e ingresar cada fragmento en la segunda tabla usando la referencia al término general en el primera tabla para completar la relación. De esta manera, está haciendo la disección en PHP, pero dejando que mySQL o cualquier base de datos haga la optimización del índice por usted. Puede ser útil en la fase de bigrama almacenar el número de bigramas realizados en la tabla 1 para la fase de cálculo. A continuación se muestra un código en PHP para darle una idea de cómo crear los bigramas:

// split the string into len-character segments and store seperately in array slots
function get_bigrams($theString,$len)   
{
   $s=strtolower($theString);
   $v=array();
   $slength=strlen($s)-($len-1);     // we stop short of $len-1 so we don't make short chunks as we run out of characters

   for($m=0;$m<$slength;$m++)
   {
      $v[]=substr($s,$m,$len);
   }
   return $v;
}    

No se preocupe por los espacios en las cadenas; en realidad, son muy útiles si piensa en la búsqueda difusa.

Así que obtienes los bigramas, los ingresas en una tabla, vinculados al texto general en la tabla 1 a través de una columna indexada... ¿y ahora qué?

Ahora, siempre que busque un término como "Mi término favorito para buscar", puede usar la función php para convertirlo en una matriz de bigramas. Luego usa esto para crear la parte IN (..) de una declaración SQL en su tabla de bigramas (2). A continuación se muestra un ejemplo:

select count(b_id) as matches,a.hd_id,description, from table2 a
inner join table1 b on (a.hd_id=b.hd_id)
where bigram in (" . $sqlstr . ")
group by hd_id order by matches desc limit X

Dejé el $sqlstr como una referencia de cadena de PHP:puede construirlo usted mismo como una lista separada por comas de la función bigram usando implode o lo que sea en la matriz devuelta por get_bigrams o parametrizar si lo desea también.

Si se realiza correctamente, la consulta anterior devuelve los términos de búsqueda aproximada más coincidentes según la longitud del bigrama que elija. La longitud que elija tiene una eficacia relativa basada en la longitud esperada de las cadenas de búsqueda generales.

Por último, la consulta anterior solo proporciona una clasificación de coincidencia aproximada. Puede jugar y mejorar comparando no solo las coincidencias, sino también las coincidencias con el recuento general de bigramas, lo que ayudará a eliminar el sesgo de las cadenas de búsqueda largas en comparación con las cadenas cortas. Me detuve aquí porque en este momento se vuelve mucho más específico para la aplicación.

¡Espero que esto ayude!

R