Использование SIMILAR TO вместе со ALL в PostgreSQL - PullRequest
0 голосов
/ 08 октября 2019

Я хотел бы определить, возможно ли использовать SIMILAR TO в сочетании с ANY или ALL в запросе PostgreSQL.

Это для LIKE, то есть я могу сделать:

SELECT 'man bear pig' LIKE ANY(ARRAY['%fish%', '%bear%']);

Попытка сделать то же самое с SIMILAR TO:

SELECT 'man bear pig' SIMILAR TO ANY(ARRAY['%fish%', '%bear%']);

, который возвращает ошибку:

[42601] ERROR: syntax error at or near "ANY"
Position: 34

В этом случае это не делаетбольшая разница, но, скажем, я хочу использовать расширенный синтаксис, например %(man|pig)%, тогда LIKE вернет результат, отличный от SIMILAR TO.

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 08 октября 2019

Вы не можете сделать это напрямую, но вы можете преобразовать его так же, как это делает PostgreSQL:

SELECT 'man bear pig'
        ~ ANY (ARRAY[
                  similar_escape('%fish%', NULL),
                  similar_escape('%bear%', NULL)
               ]);

Но было бы проще использовать регулярные выражения напрямую:

SELECT 'man bear pig'
       ~ ANY (ARRAY['fish', 'bear']);
1 голос
/ 08 октября 2019

ПОХОЖИЕ НА немного странное существо. У него нет нормального оператора, с которым он сопоставляется (как «LIKE» сопоставляется с «~~»), поэтому, вероятно, он не работает. Скорее, он больше похож на макрос, который переписывается в терминах регулярных выражений POSIX.

explain SELECT * from pgbench_accounts where filler similar to '%(fish|bear)%';
                                     QUERY PLAN                                     
------------------------------------------------------------------------------------
 Gather  (cost=1000.00..45517.52 rows=1 width=97)
   Workers Planned: 2
   ->  Parallel Seq Scan on pgbench_accounts  (cost=0.00..44517.42 rows=1 width=97)
         Filter: (filler ~ '^(?:.*(?:fish|bear).*)$'::text)

Посмотрите, как фильтр говорит, что он использует «~», а сама строка была изменена?

Таким образом, одним из ответов будет использование в первую очередь регулярных выражений POSIX, а не SIMILAR TO. Если вам это не нравится, вы можете создать свой собственный оператор:

create function similar_to(text, text) returns bool language SQL as $$ select $1 similar to $2 $$;
create operator ~^~ (function = similar_to, leftarg=text, rightarg=text);

SELECT 'man bear pig' ~^~ ANY(ARRAY['%fish%', '%bear%']);

Имя «~ ^ ~» было выбрано произвольно, вы можете подумать, как его назвать, чем я. .

Это, вероятно, не самый эффективный способ сделать что-либо, и он наверняка победит любой индекс (например, pg_trgm), который в противном случае мог бы быть использован.

...