对 ANY(数组)使用 LIKE?

问题描述 投票:0回答:2
select sum(case when '%sys%' like any(series_arr)
                  or 'displays' = any(lob_arr)
                then revenue else 0 end) as sys_displ_revenue
from mytable

基本上,当我运行此查询时,术语

'%sys%' like any(<array column>
) 似乎被忽略,并且仅使用“显示”收入。

如何解决这个问题?

sql arrays postgresql sql-like
2个回答
2
投票
  1. 所有 PostgreSQL 模式匹配 运算符都接受字符串作为其左操作数,并将模式作为其右操作数。您的代码尝试执行相反的顺序。
  2. 正如 @mandy8055 最初建议的那样,您可以
    unnest()
    并对每个元素使用
    like
  3. sum(case)
    条件聚合构造可以替换为
    filter
    子句

db<>fiddle 的演示:

select sum(revenue)filter(where exists(select from unnest(series_arr)_(e) 
                                       where e like '%sys%')
                          or 'displays' = any(lob_arr)) as sys_displ_revenue
from mytable

1
投票

您可以将

LIKE
ANY
结构一起使用。但模式位于操作数的右侧,并且
LIKE
(或者更确切地说,它是内部实现
~~
)没有
COMMUTATOR

自定义运算符

有了必要的权限,您可以创建自己的自定义运算符以使其工作:

CREATE FUNCTION reverse_like (text, text)
  RETURNS boolean
  LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE COST 10
RETURN $2 LIKE $1;

CREATE OPERATOR <~~ (
  FUNCTION = reverse_like
, LEFTARG  = text
, RIGHTARG = text
);

然后:

SELECT sum(CASE WHEN '%sys%' <~~ ANY (series_arr)
                  OR 'displays' = ANY (lob_arr) THEN revenue END) AS sys_displ_revenue
FROM   mytable;

我跳过了

ELSE 0
。如果没有
ELSE
,SQL
CASE
默认为
null
,并且 sum 无论如何都会忽略 null。仅当所有行的计算结果均为
null
时才会产生影响,在这种情况下,您将得到 null 而不是 0(您可能希望使用
COALESCE
来捕获它)。

请注意,您无法通过运算符右侧的索引列获得(直接)索引支持。但这对于您的查询来说并不重要,无论如何都会对表进行完整的顺序扫描。

参见:

顺便说一句,我正在使用“标准 SQL”函数的最小语法。参见:

没有自定义运算符

除此之外,相关子查询可以完成这项工作:

SELECT sum(CASE WHEN (SELECT bool_or(s ~ 'sys') FROM unnest (series_arr) s)
                  OR 'displays' = ANY (lob_arr) THEN revenue ELSE 0 END) AS sys_displ_revenue
FROM   mytable t

使用更简单的正则表达式运算符

~
,但都是一样的。

我会使用后者,除非您可以在不仅仅是这个查询中充分利用自定义运算符。

© www.soinside.com 2019 - 2024. All rights reserved.