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.