首页 > 解决方案 > Postgres 将数组中的每个元素与通配符进行比较

问题描述

我在 postgres 中有一个数组,我正在尝试使用通配符比较单个元素。以下是我所追求的。

 SELECT '{abcdefg,hijklmnop}'::TEXT[] ILIKE '{%cde%}'::TEXT[];       --> TRUE
 SELECT '{abcdefg,hijklmnop}'::TEXT[] ILIKE '{%cde%,%foo%}'::TEXT[]; --> FALSE
 SELECT '{abcdefg,hijklmnop}'::TEXT[] ILIKE '{%cde%,%mno%}'::TEXT[]; --> TRUE

标签: arrayspostgresql

解决方案


实际上,您正在检查第二个数组中的所有模式是否与第一个数组中的任何项目匹配。

很容易检查第一个数组中的所有项目是否在模式数组中匹配SELECT EVERY(u ILIKE ANY('{%pattern%}')) FROM UNNEST('{values}') AS u( '不匹配但它返回TRUE)。

我能想到的唯一方法是将第一个数组中的每个单独的项目与每个单独的模式进行比较,并说每个模式必须至少有一个匹配项。

这很丑陋,但它给出了正确的结果。(你总是可以将它包装在一个函数中。)

SELECT EVERY(match)
FROM (
    SELECT BOOL_OR(value ILIKE pattern) AS match
    FROM UNNEST('{%cde%,%mno%}'::TEXT[]) AS pattern
    JOIN UNNEST('{abcdefg,hijklmnop}'::TEXT[]) AS value
        ON TRUE
    GROUP BY pattern
) AS matches

因此,首先它取消了数组的嵌套,以便将每个值分别与每个模式进行比较。(您可以通过将值与模式数组进行比较,value ILIKE ANY('{your patterns}')但我相信,如果没有取消嵌套,则无法将值数组与模式进行比较。)

它执行 BOOL_OR 并按模式分组,因此我们得到每个模式一个结果;结果是:该模式的值是否有任何匹配?

然后外部查询执行 EVERY(与 BOOL_AND 相同)来检查每个结果是否为真(即每个模式都已匹配);如果是,则返回 TRUE,否则返回 FALSE。


推荐阅读