Symbol wieloznaczny PostgreSQL TAK jak dowolna lista słów


156

Mam prostą listę ~ 25 słów. Mam pole varchar w PostgreSQL, powiedzmy, że jest to lista ['foo', 'bar', 'baz']. Chcę znaleźć dowolny wiersz w mojej tabeli, który zawiera którekolwiek z tych słów. To zadziała, ale chciałbym coś bardziej eleganckiego.

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

Odpowiedzi:


165

Możesz użyć SIMILAR TOoperatora Postgresa , który obsługuje alternacje, tj

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

1
Regex może to trochę przyspieszyć
około niebieskiego.

Skąd to wiedziałeś ? większość dokumentacji, którą przeczytałem, mówi, że wyrażenia regularne są wolniejsze i LIKE% ...
DestyNova

5
Według dba.stackexchange.com/a/10696/27757 SIMILAR TO jest wewnętrznie tłumaczone na wyszukiwanie wyrażeń regularnych
Mark K Cowan

Myślę, że używanie lower()jest nieskuteczne, ponieważ najpierw konwertuje każdy ciąg na małe litery, co jest bardziej kosztowne niż tylko dopasowanie
bez rozróżniania

228

PostgreSQL obsługuje również pełne wyrażenia regularne POSIX :

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

Jest ~*to dopasowanie bez rozróżniania wielkości liter, rozróżnia wielkość liter ~.

Inną opcją jest użycie DOWOLNEGO :

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

Możesz użyć DOWOLNEGO z dowolnym operatorem, który zwraca wartość logiczną. Podejrzewam, że opcje regex byłyby szybsze, ale KAŻDY jest przydatnym narzędziem, które należy mieć w swoim zestawie narzędzi.


Co ciekawe, chociaż obie te metody są bardziej eleganckie niż rozwiązanie @chmulliga (a więc +1), sprawdzając przynajmniej 3 opcje, wykonują się one znacznie wolniej na dużych tabelach (w moim przypadku 91,5 miliona rekordów). Używając któregokolwiek z nich, zauważyłem około dwukrotny wzrost czasu. Masz jakiś pomysł, dlaczego tak może być?
sage88,

@ sage88 Nie wiem z góry, ale Erwin Brandstetter może i dodanie indeksów trygramowych może pomóc.
mu jest za krótkie

13

Właściwie jest do tego operator w PostgreSQL:

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


Czy zatem ilike może być używany z dowolną & tablicą w ten sam sposób? Wygląda to porządnie, jeśli nie ma potrzeby stosowania fantazyjnych wyrażeń regularnych. A może mimo to zostanie przetłumaczone wewnętrznie na wyrażenia regularne?
mlt

@mlt To dobre pytanie, przeczytanie tego dokumentu nie daje jednoznacznej odpowiedzi. SIMILAR TOkonwertuje na wyrażenie regularne, ~operator oznacza wyrażenie regularne POSIX, ale nie jest to jasne dla LIKE.
jlandercy

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.