12

我正在尝试获取类型列text[]包含类似于某些用户输入的值的行。

到目前为止,我的想法和所做的就是像这样使用'ANY'and 'LIKE' 运算符:

select * from someTable where '%someInput%' LIKE ANY(someColum);

但它不起作用。该查询返回与该查询相同的值:

select * from someTable where 'someInput' = ANY(someColum);

unnest()在子查询中使用该函数得到了很好的结果,但如果可能的话,我需要在WHERE子句中查询这个。

为什么操作员不与LIKE操作员一起工作ANY并且我没有收到任何错误?我认为一个原因应该是ANY运算符在查询的右侧,但是......

如果不使用,是否有任何解决方案unnest(),如果可能的话WHERE

4

4 回答 4

17

同样重要的是要了解它ANY 不是运算,而是只能用于运算符右侧的 SQL 构造。更多的:

LIKE运算符 - 或者更准确地说:表达式,在 Postgres 内部被重写为~~ 运算符- 期望左侧的值和右侧的模式。这个运算符没有COMMUTATOR(就像简单的相等运算符一样=),所以 Postgres 不能翻转操作数。

您的尝试:

select * from someTable where '%someInput%' LIKE ANY(someColum);

左右翻转了操作数,因此数组列'%someInput%'someColum和元素被视为模式(这不是您想要的)。

必须是- 除了仅允许在运算符右侧ANY(someColum) LIKE '%someInput%'的构造之外,这是不可能的。你在这里遇到了障碍。ANY

有关的:

您可以规范化您的关系设计并将数组元素保存在单独表格的单独行中。除此之外,这unnest()是解决方案,因为您已经找到了自己。但是,虽然您只对是否存在至少一个匹配元素感兴趣,但EXISTS子查询将是最有效的,同时避免结果中的重复 - Postgres 可以在找到第一个匹配项后立即停止搜索:

SELECT *
FROM   tbl
WHERE  EXISTS (
    SELECT -- can be empty 
    FROM   unnest(someColum) elem
    WHERE  elem LIKE '%someInput%'
  );

您可能想转义someInput. 看:

在可能涉及的情况下小心否定 ( NOT LIKE ALL (...)) :NULL

于 2016-01-07T15:03:31.590 回答
8

我的问题被标记为重复,并被一个粗心的 mod 链接到一个断章取义的问题。这个问题最接近我问的问题,所以我把我的答案留在这里。(我认为这可能会帮助那些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%'
  )
);
于 2018-05-10T15:20:42.623 回答
5

一个公认的不完美的可能性可能是使用ARRAY_TO_STRING,然后LIKE对结果使用。例如:

SELECT *
FROM someTable
WHERE ARRAY_TO_STRING(someColum, '||') LIKE '%someInput%';

但是,这种方法可能存在问题,因为如果有人发现连接字符序列,他们可能会搜索两个数组元素。例如,代替{'Hi','Mom'},则连接||将返回结果。相反,期望可能是在这种情况下不会有结果,因为既不也不单独包含字符序列。i||MsomeInputHiMomi||M

于 2018-06-12T01:05:09.643 回答
0

检查一下

这个答案正是我想要的。如果您需要更大的灵活性,它还提供了一些有用的提示(和示例)。

它基本上解释了ANY()@>&&运算符。

"如果要搜索多个值,可以使用@> 运算符"

"@> 表示包含该数组中的所有值。如果要搜索当前数组是否包含另一个数组中的任何值,可以使用 &&"

于 2020-05-14T19:31:34.663 回答