在PostgreSQL中将SIMILAR TO与ALL一起使用

时间:2019-10-08 14:14:39

标签: postgresql postgresql-10

我想确定在PostgreSQL查询中是否可以将SIMILAR TOANYALL结合使用。

它适用于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 个答案:

答案 0 :(得分:2)

您不能直接执行它,但是可以像PostgreSQL一样进行转换:

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

但是直接使用正则表达式会更简单:

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

答案 1 :(得分:1)

类似TO是有点奇怪的生物。它没有映射到的普通运算符(“ 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)。