如何使用ANY数组运算符的正则表达式

时间:2014-02-28 15:05:29

标签: regex arrays postgresql

我有一个包含作者数组的列。如何使用~*运算符检查其任何值是否与给定的正则表达式匹配?

~*运算符在左侧检查字符串,在右侧检查正则表达式。文档说ANY运算符必须在右侧,显然

SELECT '^p' ~* ANY(authors) FROM book;

不起作用,因为PostgreSQL尝试将字符串^p与数组中包含的表达式进行匹配。

有什么想法吗?

6 个答案:

答案 0 :(得分:8)

第一个明显的想法是使用您自己的regexp匹配运算符和commuted arguments:

create function commuted_regexp_match(text,text) returns bool as
'select $2 ~* $1;'
language sql;

create operator ~!@# (
 procedure=commuted_regexp_match(text,text),
 leftarg=text, rightarg=text
);

然后你可以像这样使用它:

SELECT '^p' ~!@# ANY(authors) FROM book;

另一种不同的方式来查看它以取消数组并在SQL中制定等效的ANY结构:

select bool_or(r) from 
  (select author ~* '^j' as r
    from (select unnest(authors) as author from book) s1 
  ) s2;

答案 1 :(得分:1)

您可以定义自己的运算符来执行您想要的操作。

颠倒参数的顺序并调用相应的函数:

create function revreg (text, text) returns boolean 
language sql immutable 
as $$ select texticregexeq($2,$1); $$;

(revreg ...请选择您喜欢的名字)。

使用我们的revreg()函数添加一个新运算符:

CREATE OPERATOR ### (
    PROCEDURE = revreg,
    LEFTARG = text,
    RIGHTARG = text
 );

测试:

 test=# SELECT '^p' ### ANY(ARRAY['ika', 'pchu']);
  t
 test=# SELECT '^p' ### ANY(ARRAY['ika', 'chu']);
  f
 test=# SELECT '^p' ### ANY(ARRAY['pika', 'pchu']);
  t
 test=# SELECT '^p' ### ANY(ARRAY['pika', 'chu']);
  t

请注意,您可能需要将JOIN和RESTICT子句设置为new运算符以帮助计划程序。

答案 2 :(得分:1)

我用这个:

create or replace function regexp_match_array(a text[], regexp text)
returns boolean
strict immutable
language sql as $_$
select exists (select * from unnest(a) as x where x ~ regexp);
$_$;

comment on function regexp_match_array(text[], text) is
  'returns TRUE if any element of a matches regexp';

create operator ~ (
 procedure=regexp_match_array,
 leftarg=text[], rightarg=text
);

comment on operator ~(text[], text) is
  'returns TRUE if any element of ARRAY (left) matches REGEXP (right); think ANY(ARRAY) ~ REGEXP';

然后使用它就像你使用〜文本标量一样:

=> select distinct gl from x where gl ~ 'SH' and array_length(gl,1) < 7;
┌──────────────────────────────────────┐
│                  gl                  │
├──────────────────────────────────────┤
│ {MSH6}                               │
│ {EPCAM,MLH1,MSH2,MSH6,PMS2}          │
│ {SH3TC2}                             │
│ {SHOC2}                              │
│ {BRAF,KRAS,MAP2K1,MAP2K2,SHOC2,SOS1} │
│ {MSH2}                               │
└──────────────────────────────────────┘
(6 rows)

答案 3 :(得分:1)

我的解决方案

SELECT a.* FROM books a
CROSS JOIN LATERAL (
   SELECT author
   FROM unnest(authors) author
   WHERE author ~ E'p$'
   LIMIT 1
)b;

使用交叉横向连接,对表格的每一行评估子查询,并且#34;如果其中一行返回的条件符合条件,则子查询返回一行(因为限制)。

答案 4 :(得分:1)

SELECT * FROM book where   EXISTS ( SELECT * from unnest(author) as X where x ~* '^p' )  

答案 5 :(得分:1)

如果您可以对数据做出合理的假设,这里有一个想法。只需将数组连接成一个字符串,然后对整个字符串进行正则表达式搜索。

select array_to_string(ARRAY['foo bar', 'moo cow'], ',') ~ 'foo'

袖手旁观,没有任何测量来支持我,我想说与正则表达式相关的大多数性能问题都可以通过巧妙地使用正则表达式来解决,也许还有一些特殊的分隔符。创建字符串可能是一个性能问题,但我什至不敢推测。