我试图获取这样的行,其中text[]
类型的列包含类似于某个用户输入的值。
到目前为止,我所考虑和做的是像这样使用'ANY'
和'LIKE
'运算符:
select * from someTable where '%someInput%' LIKE ANY(someColum);
但它不起作用。该查询返回的值与下面的查询相同:
select * from someTable where 'someInput' = ANY(someColum);
我在子查询中使用unnest()
函数得到了很好的结果,但是如果可能的话,我需要在WHERE
子句中查询它。
为什么LIKE
操作符不能与ANY
操作符一起工作,并且我没有得到任何错误?我认为一个原因应该是ANY
操作符在查询的右边,但是...
是否有任何不使用unnest()
的解决方案,以及WHERE
子句中是否可能?
4条答案
按热度按时间guicsvcw1#
ANY
*不是 * 运算符,而是只能用于运算符 * 右侧 * 的SQL构造。详细信息:LIKE
运算符--或者更准确地说:* 关键字 *,在Postgres内部重写为~~
运算符-期望左边的 value 和右边的 pattern。这个运算符没有COMMUTATOR
(就像简单的相等运算符=
一样),所以Postgres不能翻转操作数。您的尝试:
...左右操作数反向。
'%someInput%'
是 value,数组列someColum
的元素被视为模式,这不是您想要的。它 * 应该 * 是类似 *
ANY (someColum) LIKE '%someInput%'
* 的东西--但是ANY
结构只允许放在操作符的 * 右边 *。相关:
您可以规范化关系设计,并将数组的 elements 保存在单独表的单独行中。除此之外,**
unnest()
是解决方案,正如您已经发现的那样。但是,尽管您只对至少存在一个匹配元素感兴趣,一个EXISTS
**子查询将是最有效的,并且避免了结果中的重复。Postgres可以在找到第一个匹配项时立即停止搜索:您可能需要对
someInput
中的特殊字符进行转义。请参阅:小心在可能涉及
NULL
时使用否定(NOT LIKE ALL (...)
):6mzjoqzu2#
一个公认的不完美的可能性是使用
ARRAY_TO_STRING
,然后对结果使用LIKE
。但是,这种方法存在潜在的问题,因为如果有人发现连接字符序列,他们可能会搜索两个数组元素。例如,如果用户输入
i||M
而不是someInput
,则与||
连接的{'Hi','Mom'}
数组将返回结果。相反,预期可能是在这种情况下没有结果,因为Hi
和Mom
都不单独包含i||M
字符序列。643ylb083#
我的question被一个粗心的mod标记为重复并链接到一个断章取义的问题。这个问题与我问的最接近,所以我在这里留下我的答案。(我认为这可能会帮助人们了解
unnest()
是一个解决方案)在我的例子中,
DISTINCT
和unnest()
的组合是解决方案:unnest(tags)
将文本数组扩展为行列表,DISTINCT ON (id_)
根据唯一的id_
列删除扩展产生的重复项。更新
另一种在
WHERE
子句中不使用DISTINCT
的方法是:tvmytwxo4#
拜托。
这个答案正是我要找的。它还提供了一些有用的提示(和示例),以防您需要更多的灵活性。
它基本上解释了ANY()、**@〉和&&**操作符。