PostgreSQL - text Array contains value similar to

六月ゝ 毕业季﹏ 提交于 2019-11-28 12:38:37
Erwin Brandstetter

It's also important to understand that ANY is not an operator but an SQL construct that can only be used to the right of an operator. More:

The LIKE operator - or more precisely: expression, that is rewritten with to the ~~ operator in Postgres internally - expects the value to the left and the pattern to the right. There is no COMMUTATOR for this operator (like there is for the simple equality operator =) so Postgres cannot flip operands around.

Your attempt:

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

has flipped left and right operand so '%someInput%' is the value and elements of the array column someColum are taken to be patterns (which is not what you want).

It would have to be ANY(someColum) LIKE '%someInput%' - except that's not possible with the ANY construct which is only allowed to the right of an operator. You are hitting a road block here.

Related:

unnest() is the solution, as you already found yourself - or save elements instead of an array to begin with (normalize the schema).

My question was marked duplicate and linked to a question out of context by a careless mod. This question here comes closest to what I asked so I leave my answer here. (I think it may help people for who unnest() would be a solution)

In my case a combination of DISTINCT and unnest() was the solution:

SELECT DISTINCT ON (id_) *
FROM (
  SELECT unnest(tags) tag, *
  FROM someTable
  ) x
WHERE (tag like '%someInput%');

unnest(tags) expands the text array to a list of rows and DISTINCT ON (id_) removes the duplicates that result from the expansion, based on a unique id_ column.

Update

Another way to do this without DISTINCT within the WHERE clause would be:

SELECT *
FROM someTable 
WHERE (
  0 < (
    SELECT COUNT(*) 
    FROM unnest(tags) AS tag
    WHERE tag LIKE '%someInput%'
  )
);

An admittedly imperfect possibility might be to use ARRAY_TO_STRING, then use LIKE against the result. For example:

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

This approach is potentially problematic, though, because someone could search over two array elements if they discover the joining character sequence. For example, an array of {'Hi','Mom'}, connected with || would return a result if the user had entered i||M in place of someInput. Instead, the expectation would probably be that there would be no result in that case since neither Hi nor Mom individually contain the i||M sequence of characters.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!