web-dev-qa-db-fra.com

Recherche de "correspondance complète de mots" dans MySQL

Je voudrais écrire une requête SQL qui recherche un mot-clé dans un champ de texte, mais seulement s'il s'agit d'une "correspondance de mot entier" (par exemple, lorsque je recherche "débarrasser", il ne doit pas correspondre à "aride", mais il doit correspondre à "un débarrasser".

J'utilise MySQL.

Heureusement, les performances ne sont pas critiques dans cette application, et la taille de la base de données et la taille de la chaîne sont toutes deux confortablement petites, mais je préférerais le faire dans le SQL que dans le PHP le pilotant).

68
Oddthinking

Vous pouvez utiliser REGEXP et le [[:<:]] et [[:>:]] Marqueurs de limites de mots:

SELECT *
FROM table 
WHERE keywords REGEXP '[[:<:]]rid[[:>:]]'
142
LukeH

Trouvé une réponse pour éviter la limite classique de Word [[::<::]] affrontement avec des caractères spéciaux, par exemple. @ # $% ^ & *

Remplacer..

SELECT *
FROM table 
WHERE keywords REGEXP '[[:<:]]rid[[:>:]]'

Avec ça..

SELECT *
FROM table 
WHERE keywords REGEXP '([[:blank:][:punct:]]|^)rid([[:blank:][:punct:]]|$)'

Cette dernière correspond (espace, tabulation, etc.) || (virgule, crochet, etc.) || début/fin de ligne. Une correspondance de limite de mot plus "terminée".

28
Ricky Boyce

Vous pouvez utiliser like avec le marqueur générique pour saisir les possibilités (au début, à la fin, au milieu et seul), quelque chose comme ça devrait suffire:

sélectionnez bla bla bla où une colonne comme 'rid%' ou une colonne comme '% rid' ou une colonne comme '% rid%' ou une colonne = 'rid'

5
paxdiablo

Utilisez l'expression rationnelle avec les limites de Word, mais si vous souhaitez également une recherche insensible aux accents, veuillez noter que REGEXP est un opérateur à un octet, donc il ne vaut rien d'avoir le classement utf8_general_ci, la correspondance ne sera pas insensible aux accents.

Pour que les mots insensibles aux accents et les mots entiers correspondent, spécifiez le mot écrit de la même manière que la fonction (obsolète) PHP sql_regcase () l'a fait.

En réalité:

  • utf8_general_ci vous permet de faire une casse d'égalité (champ WHERE = valeur) et d'accentuer la recherche insensible mais il ne vous permet pas de spécifier une correspondance Word complète (les marqueurs de limites de mot ne sont pas reconnus)

  • LIKE vous permet une recherche insensible à la casse et à l'accent, mais vous devez spécifier manuellement toutes les combinaisons de caractères possibles des limites de Word (marqueurs de limites de Word non reconnus)

  • Les limites de mots [[: <:]] et [[:>:]] sont prises en charge dans REGEXP, qui est une fonction à un octet, donc n'effectuez pas de recherche insensible aux accents.

La solution consiste à utiliser REGEXP avec les limites de Word et le Word modifié comme le fait sql_regcase.

Utilisé sur http://www.nonsolodiete.it

3
Marco Marsala
select * from table where Locate('rid ', FieldToSearch) > 0 
      or Locate(' rid', FieldToSearch) > 0

Cela permettra de se débarrasser de l'endroit où il est précédé ou suivi d'un espace, vous pouvez étendre l'approche pour tenir compte de.,?! et ainsi de suite, pas élégant mais facile.

1
MrTelly

C'est la meilleure réponse que j'ai trouvée jusqu'à présent:

SELECT * FROM table 
WHERE keywords REGEXP '^rid[ $]' OR keywords REGEXP ' rid[ $]'

Je l'aurais simplifié pour:

SELECT *
FROM table
WHERE keywords REGEXP '[^ ]rid[ $]'

mais [^] a une signification spéciale de "PAS un espace", plutôt que "début de ligne ou espace".

Comment REGEXP se compare-t-il à plusieurs conditions LIKE? (Pas que les performances comptent dans cette application.)

1
Oddthinking