Я пытаюсь найти способ отфильтровать записи на основе запроса, но понятия не имею, как это сделать в том же операторе:
Запрос:
select unnest(array_cat(a.object_references, a.dependent_object_references))
from mgmt.log_metrics a
Ввод:
Select предоставит записи в следующем формате:
и на выходе мне нужно фильтровать на основе r, чтобы получить все записи таблицы. Не знаю, как этого добиться, используя приведенный выше запрос.
Выход:
Я пытался применить предложение where, а также пытался поставить substring(), но после исследования обнаружил, что substring() не будет работать напрямую с unnest(). Также попробовал функцию right(), но я новичок, поэтому не знаю, как этого добиться.
Привет @JohnH. Спасибо за ответ. Мне не нужен код, просто подсказка, например, что мне делать, чтобы отфильтровать записи, содержащие букву «r» во входных данных, должно быть хорошо. У меня нет опыта фильтрации данных из запроса unnest. если какой-либо пример или помощь будут высоко оценены.





Вызов табличной функции или функции, возвращающей набор , такой как unnest() в списке select, довольно распространен, но это скорее синтаксический ярлык, а не обычное место для них. Ваш код эффективно делает это:
демо на db<>fiddle
select arr.element
from mgmt.log_metrics as a
cross join lateral unnest(array_cat( a.object_references
,a.dependent_object_references)) as arr(element)
Когда вы структурируете его таким образом, становится немного яснее, что вы можете просто добавить where, чтобы отфильтровать некоторые элементы, полученные в результате unnestобъединения объединенных массивов:
select arr.element
from mgmt.log_metrics as a
cross join lateral unnest(array_cat( a.object_references
,a.dependent_object_references)) as arr(element)
where arr.element='r';
Если вы предпочитаете изменить массив перед его отменой, вы можете использовать array_remove():
select id, unnest(array_remove( array_cat( a.object_references
,a.dependent_object_references)
,'r'))
from mgmt.log_metrics as a;
Если вы разбирали массив просто для доступа к отдельным элементам для выполнения поиска/фильтрации, но на выходе вам снова нужны массивы целиком, вы можете полностью удалить unnest() и использовать оператор включения @>:
select b.arr
from mgmt.log_metrics as a
cross join lateral array_cat( a.object_references
,a.dependent_object_references) as b(arr)
where b.arr @> array['r'];
Если вам также необходимо учитывать положение элемента в массиве, вы можете использовать квадратные скобки [] для индексации. Обычные массивы SQL в Postgres не поддерживают отрицательные индексы для проверки последнего элемента, второго от последнего и т. д., но для достижения этого вы можете действовать относительно array_length():
select a.id, b.arr
from mgmt.log_metrics as a
cross join lateral array_cat( a.object_references
,a.dependent_object_references) as b(arr)
where b.arr[array_length(b.arr,1)] = 'r';
И если вам удобно сохранять позиции или вы хотите знать их, когда вам unnest() нужно что-то еще, вы можете использовать с порядковым номером (как и в любом SRF):
select u.position, u.element
from mgmt.log_metrics as a
cross join lateral array_cat( a.object_references
,a.dependent_object_references) as b(arr)
cross join lateral unnest(b.arr) WITH ORDINALITY as u(element,position)
where u.element='r'
and u.position=array_length(b.arr,1);
Предполагая, что ваше условие фильтра должно находиться в последнем элементе массива (... Также пробовалась функция Right...) - возможно, это поможет вам найти выход из этого:
WITH -- S a m p l e D a t a :
tbl AS
( Select 1 as id, Array['a', 'b', '**r**'] as arr_data Union All
Select 2 as id, Array['c', 'd', '**r**'] as arr_data Union All
Select 3 as id, Array['e', 'l', 'v'] as arr_data Union All
Select 4 as id, Array['g', 'h', 'i', 'f'] as arr_data
)
-- S Q L :
Select t.id, t.arr_data
From tbl t
Cross Join Lateral unnest( arr_data ) WITH ORDINALITY elem_val
Where ordinality = array_length( arr_data, 1 ) And -- last element
elem_val = '**r**' -- adjust this condition to your actual data and context
/* R e s u l t :
id arr_data
-- ----------------
1 {a,b,**r**}
2 {c,d,**r**} */
См. dbfiddle здесь.
e.id, поэтому конструкция sum(1), count(*) или row_number()over(Partition By e.id Order By e.id) ненадежна. Это может и в какой-то момент приведет к совершенно другому порядку по сравнению с тем, как элементы расположены на самом деле: демо. Это также немного медленнее.
@Zegarek Ты, конечно, прав, моя ошибка. Спасибо, я обновил код.
Отсутствие подробностей затрудняет определение того, что вы пытаетесь сделать. Пожалуйста, просмотрите минимальный воспроизводимый пример и обновите свой пост соответствующим DDL. Не просто описывайте свои попытки, покажите реальные запросы. Абстрактные описания полезны, но конкретные примеры входных данных и желаемых результатов помогают другим понять, о чем спрашивают.