Підстановочний код 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%')

Відповіді:


165

Ви можете використовувати SIMILAR TOоператор Postgres, який підтримує чергування, тобто

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

1
Regex може трохи пришвидшити це: dba.stackexchange.com/questions/10694/…
приблизно

Звідки ти це знаєш? Більшість документації, яку я прочитав, говорить про те, що регулярні
виразки

5
Згідно з dba.stackexchange.com/a/10696/27757 SIMILAR TO внутрішньо перекладається на пошук регулярного виразів
Марк К Коуан

Я вважаю, що використання lower()малоефективне, оскільки спочатку перетворить кожну рядок у малі регістри, що коштує дорожче, ніж лише збіг, що не
враховує

228

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 Я не знаю в голові, але може допомогти Ервін Брандштеттер і додавання індексів триграм .
mu занадто короткий

13

Насправді в PostgreSQL є оператор:

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


Так чи можна одночасно використовувати ike з будь-яким & масивом? Це виглядає чисто, якщо немає необхідності у вигадливій виразці. Або все одно це буде переведено на регулярний вираз?
mlt

@mlt Це гарне запитання, читання документа не дає явної відповіді. SIMILAR TOконвертує в регулярну вираз, ~оператор розшифровується як регулярний вираз POSIX, але це не зрозуміло для LIKE.
jlandercy

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.