Mysql
 sql >> Base de données >  >> RDS >> Mysql

Modèle comparant avec mysql entre deux colonnes de tables

Deux questions :les descriptions sont-elles standard (les descriptions ne changent pas) ou sont-elles saisies par un utilisateur ? S'ils sont standard, ajoutez une colonne qui est un entier et effectuez une comparaison sur cette colonne.

S'il est entré par l'utilisateur, votre travail est plus compliqué car vous recherchez quelque chose qui est plus flou. J'ai utilisé un algorithme de recherche bi-gramme pour classer la similarité entre deux chaînes, mais cela ne peut pas être fait directement dans mySQL.

Au lieu d'une recherche floue, vous pouvez utiliser LIKE, mais son efficacité est limitée à l'analyse de table si vous finissez par mettre le '%' au début du terme de recherche. En outre, cela implique que vous pouvez obtenir une correspondance sur la partie de sous-chaîne que vous choisissez, ce qui signifie que vous devez connaître la sous-chaîne à l'avance.

Je serais heureux d'en dire plus une fois que je saurai ce que vous essayez de faire.

EDIT1 :Ok, compte tenu de votre élaboration, vous devrez effectuer une recherche de style flou comme je l'ai mentionné. J'utilise une méthode bi-gramme, qui consiste à prendre chaque entrée faite par l'utilisateur et à la diviser en morceaux de 2 ou 3 caractères. Je stocke ensuite chacun de ces morceaux dans une autre table avec chaque entrée liée à la description réelle.

Exemple :

Description1 :"Une course rapide vers l'avant"Description2 :"Une courte course vers l'avant"

Si vous divisez chacun en 2 morceaux de caractères - 'A', 'f', 'fa', 'as', 'st' .....

Ensuite, vous pouvez comparer le nombre de morceaux de 2 caractères qui correspondent aux deux chaînes et obtenir un "score" qui indiquera l'exactitude ou la similitude entre les deux.

Étant donné que je ne sais pas quel langage de développement vous utilisez, je laisserai de côté l'implémentation, mais c'est quelque chose qui devra être fait pas explicitement dans mySQL.

Ou l'alternative paresseuse serait d'utiliser un service de recherche dans le cloud comme Amazon qui fournira une recherche basée sur les termes que vous lui donnez... je ne sais pas s'ils vous permettent d'ajouter en permanence de nouvelles descriptions à prendre en compte, et selon votre application, il peut être un peu coûteux (à mon humble avis).

R

Pour un autre article SO sur l'implémentation du bigramme - voir ceci SO biggram / fuzzy search

--- Mise à jour par élaboration du questionneur ---

Tout d'abord, je suppose que vous avez lu la théorie sur les liens que j'ai fournis. bien)

Ok, donc la méthode bigram fonctionne bien pour créer/comparer des tableaux en mémoire uniquement si les correspondances possibles sont relativement petites, sinon elle souffre assez rapidement d'une performance d'analyse de table comme une table mysql sans index. Donc, vous allez utiliser les points forts de la base de données pour vous aider à faire l'indexation pour vous.

Ce dont vous avez besoin est une table pour contenir les "termes" ou le texte saisis par l'utilisateur que vous cherchez à comparer. La forme la plus simple est un tableau à deux colonnes, l'un est un entier unique à incrémentation automatique qui sera indexé, nous appellerons hd_id ci-dessous, le second est un varchar(255) si les chaînes sont assez courtes, ou TEXT si elles peuvent obtenir longtemps - vous pouvez nommer ce que vous voulez.

Ensuite, vous devrez créer une autre table qui a au moins TROIS colonnes - une pour la colonne de référence vers la colonne auto-incrémentée de l'autre table (nous appellerons cela hd_id ci-dessous), la seconde serait un varchar() de disons 5 caractères au maximum (cela contiendra vos morceaux de bigramme) que nous appellerons "bigramme" ci-dessous, et le troisième une colonne auto-incrémentée appelée b_id ci-dessous. Cette table contiendra tous les bigrammes pour l'entrée de chaque utilisateur et sera liée à l'entrée globale. Vous voudrez indexer la colonne varchar par elle-même (ou en premier dans l'ordre dans un index composé).

Maintenant, chaque fois qu'un utilisateur saisit un terme que vous souhaitez rechercher, vous devez saisir le terme dans le premier tableau, puis disséquer le terme en bigrammes et saisir chaque morceau dans le second tableau en utilisant la référence au terme global dans le première table pour compléter la relation. De cette façon, vous faites la dissection en PHP, mais laissez mySQL ou n'importe quelle base de données faire l'optimisation de l'index pour vous. Il peut être utile dans la phase bigramme de stocker le nombre de bigrammes réalisés dans le tableau 1 pour la phase de calcul. Vous trouverez ci-dessous du code en PHP pour vous donner une idée de la façon de créer les bigrammes :

// 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;
}    

Ne vous inquiétez pas des espaces dans les chaînes - ils sont en fait très utiles si vous pensez à la recherche floue.

Donc, vous obtenez les bigrammes, les entrez dans un tableau, liés au texte global du tableau 1 via une colonne indexée... et maintenant ?

Désormais, chaque fois que vous recherchez un terme tel que "Mon terme préféré à rechercher", vous pouvez utiliser la fonction php pour le transformer en un tableau de bigrammes. Vous l'utilisez ensuite pour créer la partie IN (..) d'une instruction SQL sur votre table bigram (2). Ci-dessous un exemple :

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

J'ai laissé le $ sqlstr comme référence de chaîne PHP - vous pouvez le construire vous-même comme une liste séparée par des virgules à partir de la fonction bigram en utilisant implode ou quoi que ce soit sur le tableau renvoyé par get_bigrams ou paramétrer si vous le souhaitez aussi.

Si elle est effectuée correctement, la requête ci-dessus renvoie les termes de recherche flous les plus proches en fonction de la longueur du bigramme que vous avez choisi. La longueur que vous choisissez a une efficacité relative basée sur la longueur attendue des chaînes de recherche globales.

Enfin - la requête ci-dessus donne juste un classement de correspondance floue. Vous pouvez jouer avec et améliorer en comparant non seulement les correspondances, mais aussi les correspondances avec le nombre total de bigrammes, ce qui aidera à débiaiser les longues chaînes de recherche par rapport aux chaînes courtes. Je me suis arrêté ici car à ce stade, cela devient beaucoup plus spécifique à l'application.

J'espère que cela vous aidera !

R