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>
) 似乎被忽略,并且仅使用“显示”收入。
如何解决这个问题?
unnest()
并对每个元素使用 like
。sum(case)
条件聚合构造可以替换为filter
子句。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
您可以将
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
使用更简单的正则表达式运算符
~
,但都是一样的。
我会使用后者,除非您可以在不仅仅是这个查询中充分利用自定义运算符。