提问人:Jose Hermosilla Rodrigo 提问时间:1/7/2016 最后编辑:Erwin BrandstetterJose Hermosilla Rodrigo 更新时间:3/10/2023 访问量:24498
查找文本数组包含与输入类似的值的行
Find rows where text array contains value similar to input
问:
我正在尝试获取类型列包含类似于某些用户输入的值的行。text[]
到目前为止,我所想和所做的是像这样使用 and ' 运算符:'ANY'
'LIKE
select * from someTable where '%someInput%' LIKE ANY(someColum);
但它不起作用。查询返回的值与此查询相同:
select * from someTable where 'someInput' = ANY(someColum);
我在子查询中使用该函数得到了很好的结果,但如果可能的话,我需要在子句中查询这个。unnest()
WHERE
为什么操作员不与操作员一起工作,而我没有收到任何错误?我认为一个原因应该是运算符在查询的右侧,但是......LIKE
ANY
ANY
在不使用的情况下是否有任何解决方案,如果在子句中可能的话?unnest()
WHERE
答:
ANY
不是运算符,而是一个只能在运算符右侧使用的 SQL 构造。更多:
运算符 - 或者更准确地说:关键字,在 Postgres 内部重写给运算符 - 期望值在左边,模式在右边。此运算符没有 COMMUTATOR
(就像简单相等运算符一样),因此 Postgres 无法翻转操作数。LIKE
~~
=
您的尝试:
select * from someTable where '%someInput%' LIKE ANY(someColum);
...有左右操作数向后。 是数组列的值,并且数组列的元素被视为模式,这不是您想要的。'%someInput%'
someColum
它必须类似于 ANY (someColum) LIKE '%someInput%'
- 但构造只允许在运算符的右侧。你遇到了一个路障。ANY
相关:
您可以规范化关系设计,并将数组的元素保存在单独表中的单独行中。除此之外,unnest()
是解决方案,正如您已经找到的那样。但是,虽然您只对至少一个匹配元素的存在感兴趣,但 EXISTS
子查询将是最有效的,并且可以避免结果中的重复。Postgres 可以在找到第一个匹配项后立即停止搜索:
SELECT *
FROM tbl
WHERE EXISTS (
SELECT -- SELECT list can be empty for this purpose
FROM unnest(someColum) elem
WHERE elem LIKE '%someInput%'
);
您可能希望对 中的特殊字符进行转义。看:someInput
当可能涉及否定 () 时,请小心:NOT LIKE ALL (...)
NULL
评论
我的问题被标记为重复,并被一个粗心的模组断章取义地链接到一个问题。这个问题最接近我问的问题,所以我把我的答案留在这里。(我认为它可能会帮助人们解决)unnest()
就我而言,和的组合是解决方案:DISTINCT
unnest()
SELECT DISTINCT ON (id_) *
FROM (
SELECT unnest(tags) tag, *
FROM someTable
) x
WHERE (tag like '%someInput%');
unnest(tags)
将文本数组展开为行列表,并基于唯一列删除扩展产生的重复项。DISTINCT ON (id_)
id_
更新
另一种在没有子句的情况下执行此操作的方法是:DISTINCT
WHERE
SELECT *
FROM someTable
WHERE (
0 < (
SELECT COUNT(*)
FROM unnest(tags) AS tag
WHERE tag LIKE '%someInput%'
)
);
一个公认的不完美的可能性可能是使用ARRAY_TO_STRING
,然后对结果使用。例如:LIKE
SELECT *
FROM someTable
WHERE ARRAY_TO_STRING(someColum, '||') LIKE '%someInput%';
但是,这种方法可能会有问题,因为如果有人发现连接字符序列,他们可能会搜索两个数组元素。例如,如果用户输入了 代替 ,则连接的数组 将返回结果。相反,人们的期望可能是在这种情况下不会有结果,因为既不包含字符序列,也不单独包含字符序列。{'Hi','Mom'}
||
i||M
someInput
Hi
Mom
i||M
请检查一下。
这个答案正是我想要的。它还提供了一些有用的提示(和示例),以防您需要更大的灵活性。
它基本上解释了 ANY()、@> 和 && 运算符。
“如果要搜索多个值,可以使用 @> 运算符”
“@> 表示包含该数组中的所有值。如果要搜索当前数组是否包含另一个数组中的任何值,可以使用 &&”
评论
unnest