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%')

Ответы:


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%}');


Так можно ли использовать ilike с любым & массивом таким же образом? Это выглядит чисто, если нет необходимости в необычном регулярном выражении. Или это все равно будет переведено в regex?
MLT

@mlt Это хороший вопрос, чтение документа не дает четкого ответа. SIMILAR TOпреобразовывает в Регулярное выражение, ~оператор обозначает Регулярное выражение POSIX, но это не ясно LIKE.
Jlandercy

0

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


1
Downvote, потому что это всего лишь ссылка, которая лучше подходит для комментариев.
Тораритт
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.