Trino: Presto array contains an element that likes some pattern
Ты пишешь запрос в Trino, пытаешься отфильтровать строки, где в массиве есть элемент с нужной подстрокой. Наивно пытаешься прикрутить `LIKE` к целому массиву и
Ты пишешь запрос в Trino, пытаешься отфильтровать строки, где в массиве есть элемент с нужной подстрокой. Наивно пытаешься прикрутить LIKE к целому массиву и получаешь закономерную ошибку — так не работает. Ощущение знакомое.
Всё упирается в то, что LIKE — это оператор для скалярного типа VARCHAR. А у тебя — массив. Нужно «развернуть» проверку на каждый элемент.
Решение: any_match() и лямбда
Прямой путь — использовать функцию any_match(). Она пробегается по массиву и проверяет условие для каждого элемента.
SELECT *
FROM my_table
WHERE any_match(my_array_column, element -> element LIKE '%denied%')
Вот что здесь происходит: element -> element LIKE '%denied%' — это лямбда-функция. element — условное имя для каждого item в массиве. Стрелка -> отделяет аргумент от логического выражения, которое должно вернуть TRUE или FALSE.
Функция any_match() вернет TRUE, если хотя бы для одного элемента массива твое условие выполнится.
Если массив — это строка
Бывает, что из-за кривых данных или legacy-системы массив приезжает как строка вроде ["value1", "value2 denied"]. С таким any_match() не сработается, нужно сначала привести к типу ARRAY<VARCHAR>.
SELECT *
FROM my_table
WHERE any_match(
cast(json_parse(my_fake_array_column) as array(varchar)),
element -> element LIKE '%denied%'
)
Здесь json_parse разберет строку как JSON, а cast приведет его к настоящему массиву. После этого можно применять обычную логику.
Альтернатива: unnest + like
Есть и более классический SQL-способ через unnest() и подзапрос. Он менее эффективен, но иногда полезен для сложных условий, где одной лямбдой не обойтись.
SELECT DISTINCT t.*
FROM my_table t
CROSS JOIN unnest(t.my_array_column) AS elem(element)
WHERE elem.element LIKE '%denied%'
unnest() разворачивает массив в набор строк, к которым уже можно применить обычный LIKE. DISTINCT нужен, чтобы исходные строки таблицы не дублировались, если подходящих элементов в массиве несколько.
Итог
Когда нужно найти в массиве элемент по паттерну, твой главный инструмент — any_match() с лямбдой. Это идиоматично для Trino (ранее Presto) и работает быстро.
Порядок мыслей: проверь тип колонки — если это реальный ARRAY, пиши лямбду. Если это строка, приведи к массиву. Если запрос становится слишком сложным, разверни данные через unnest. В 95% случаев хватает первого варианта.