223 votes

PostgreSQL wildcard LIKE pour n'importe quel mot d'une liste de mots

J'ai une liste simple d'environ 25 mots. J'ai un champ varchar dans PostgreSQL, disons que cette liste est ['foo', 'bar', 'baz'] . Je souhaite trouver dans mon tableau toute ligne contenant l'un de ces mots. Cela fonctionnera, mais j'aimerais quelque chose de plus élégant.

select *
from table
where (lower(value) like '%foo%' or lower(value) like '%bar%' or lower(value) like '%baz%')

346voto

mu is too short Points 205090

PostgreSQL prend également en charge les Expressions régulières POSIX :

select * from table where value ~* 'foo|bar|baz';

En ~* correspond à une correspondance insensible à la casse, ~ est sensible à la casse.

Une autre option consiste à utiliser ANY :

select * from table where value  like any (array['%foo%', '%bar%', '%baz%']);
select * from table where value ilike any (array['%foo%', '%bar%', '%baz%']);

Vous pouvez utiliser ANY avec n'importe quel opérateur produisant un booléen. Je pense que les options regex seraient plus rapides, mais ANY est un outil utile à avoir dans sa boîte à outils.

0 votes

Il est intéressant de noter que si ces deux méthodes sont plus élégantes que la solution de @chmullig (donc +1), lorsqu'on vérifie au moins 3 options, elles s'exécutent beaucoup plus lentement sur les grandes tables (91,5 millions d'enregistrements dans mon cas). J'ai constaté une augmentation du temps d'environ 2 fois en utilisant l'une ou l'autre de ces solutions. Une idée de l'origine de ce phénomène ?

0 votes

@sage88 Je ne sais pas de mémoire, mais Erwin Brandstetter pourrait et ajoute index des trigrammes pourrait aider.

218voto

Nordic Mainframe Points 13717

Vous pouvez utiliser la fonction SIMILAR TO qui prend en charge les alternances, c'est-à-dire

select * from table where lower(value) similar to '%(foo|bar|baz)%';

1 votes

Les expressions rationnelles pourraient accélérer un peu le processus : dba.stackexchange.com/questions/10694/

0 votes

Comment le savez-vous ? la plupart des documentations que j'ai lues disent que les regex sont plus lentes et qu'un LIKE %...

7 votes

Selon le dba.stackexchange.com/a/10696/27757 SIMILAR TO est traduit en interne en une recherche par expressions rationnelles (regex)

28voto

jlandercy Points 1399

En fait, il existe un opérateur pour cela dans PostgreSQL :

SELECT *
FROM table
WHERE lower(value) ~~ ANY('{%foo%,%bar%,%baz%}');

1voto

Kalendae Points 1354

Une solution "élégante" consisterait à utiliser la recherche en texte intégral : http://www.postgresql.org/docs/9.0/interactive/textsearch.html . Ensuite, vous utiliserez des requêtes de recherche en texte intégral.

1 votes

Downvote, car ce n'est qu'un lien qui aurait mieux sa place dans un commentaire.

0voto

Aaron Thomas Points 2614

Toutes les versions actuellement prises en charge (à partir de la version 9.5) autorisent la recherche de motifs en plus de la fonction LIKE .

Référence : https://www.postgresql.org/docs/current/functions-matching.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X