PostgreSQL подстановочный знак LIKE для любого списка слов

156

У меня есть простой список ~ 25 слов. У меня есть поле varchar в PostgreSQL, скажем, список есть ['foo', 'bar', 'baz']. Я хочу найти в моей таблице любую строку, в которой есть любое из этих слов. Это будет работать, но я хотел бы что-то более элегантное.

select *
from table
where (lower(value) like '%foo%' or lower(value) like '%bar%' or lower(value) like '%baz%')
chmullig
источник

Ответы:

166

Вы можете использовать SIMILAR TOоператор Postgres, который поддерживает чередования, т.е.

select * from table where lower(value) similar to '%(foo|bar|baz)%';
Скандинавский мэйнфрейм
источник
1
Regex может немного ускорить это: dba.stackexchange.com/questions/10694/…
приблизительно
Откуда ты знаешь ? большая часть документации, которую я прочитал, говорит, что регулярные выражения медленнее и НРАВИТСЯ% ...
DestyNova
5
Согласно dba.stackexchange.com/a/10696/27757 SIMILAR TO внутренне переведен на поиск регулярных выражений
Марк К Коуэн
Я думаю, что использование lower()неэффективно, потому что сначала оно преобразует каждую строку в нижний регистр, что обходится дороже, чем сопоставление
без учета
229

PostgreSQL также поддерживает полные регулярные выражения POSIX :

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

Для ~*сопоставления без учета регистра, с ~учетом регистра.

Другой вариант - использовать ЛЮБОЙ :

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

Вы можете использовать ЛЮБОЙ с любым оператором, который выдает логическое значение. Я подозреваю, что параметры регулярного выражения будут быстрее, но ЛЮБОЙ это полезный инструмент, который есть в вашем наборе инструментов.

мю слишком коротка
источник
Интересно, что хотя оба эти метода более элегантны, чем решение @chmullig (т. Е. +1), при проверке как минимум 3 параметров они выполняются значительно медленнее на больших таблицах (в моем случае 91,5 миллиона записей). Я видел увеличение времени примерно в 2 раза при использовании любого из них. Есть идеи, почему это может быть?
sage88
@ sage88 Я не знаю, насколько это возможно, но Эрвин Брандстеттер мог бы и добавить индексы триграмм .
мю слишком коротка
13

Для этого в PostgreSQL есть оператор:

SELECT *
FROM table
WHERE lower(value) ~~ ANY('{%foo%,%bar%,%baz%}');
jlandercy
источник
Так можно ли использовать ilike с любым & массивом таким же образом? Это выглядит чисто, если нет необходимости в необычном регулярном выражении. Или это все равно будет переведено в regex?
MLT
@mlt Это хороший вопрос, чтение документа не дает четкого ответа. SIMILAR TOпреобразовывает в Регулярное выражение, ~оператор обозначает Регулярное выражение POSIX, но это не ясно LIKE.
Jlandercy
0

Одним из «элегантных» решений было бы использование полнотекстового поиска: http://www.postgresql.org/docs/9.0/interactive/textsearch.html . Тогда вы будете использовать полнотекстовые поисковые запросы.

календами
источник
1
Downvote, потому что это всего лишь ссылка, которая лучше подходит для комментариев.
Тораритт