PostgreSQL получает доступ к нескольким элементам из массива с помощью позиционного массива - PullRequest
0 голосов
/ 13 мая 2018

Я хотел бы знать, возможно ли в PostgreSQL выводить массив из нескольких элементов массива, используя другой массив, указывающий серию позиций для элементов.

Чтобы быть точным:

array1 = [1,2,1]        
array_positions(array1,'1') = {1,3}
array2 = ['hello', 'bye', 'hello']

Желаемый результат:

array2[array_positions(array1,'1')] = {'hello', 'hello'}

Я получаю ERROR: array subscript must have type integer Есть предложения?

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Недостающая часть - это функция / оператор, который возвращает элементы массива с указанных позиций (я действительно удивлен, что он отсутствует в выпуске, надеюсь, он будет исправлен). Давайте создадим их:

create or replace function array_from_positions(anyarray, int[]) returns anyarray
  immutable language sql 
as $$
  select array_agg(a.x order by b.i)
  from
    unnest($1) with ordinality as a(x,i)
      right join unnest($2) with ordinality as b(x,i) on (a.i=b.x)
$$;

Тест:

select
  array_from_positions('{a,b,c,d}'::text[], '{2,1,10}'),
  array_from_positions('{1,2,3,4}'::int[], '{2,1,10}');
┌──────────────────────┬──────────────────────┐
│ array_from_positions │ array_from_positions │
├──────────────────────┼──────────────────────┤
│ {b,a,NULL}           │ {2,1,NULL}           │
└──────────────────────┴──────────────────────┘
create operator ## (
  procedure = array_from_positions,
  leftarg = anyarray,
  rightarg = int[] );

Тест:

select
  '{a,b,c,d}'::text[] ## '{2,1,10}',
  '{1,2,3,4}'::int[] ## '{2,1,10}';
┌────────────┬────────────┐
│  ?column?  │  ?column?  │
├────────────┼────────────┤
│ {b,a,NULL} │ {2,1,NULL} │
└────────────┴────────────┘

И последний тест для вашего примера:

with your_table(array1,array2) as (values
  ('{1,2,1}'::int[], '{hello,bye,hello}'::text[]))
select array2 ## array_positions(array1, 1) from your_table;
┌───────────────┐
│   ?column?    │
├───────────────┤
│ {hello,hello} │
└───────────────┘
0 голосов
/ 13 мая 2018

Это может быть или не быть слишком сложным, чтобы быть полезным, но оно доказывает, что это возможно:

SELECT vals.*
FROM (
  VALUES(array['hello', 'bye', 'hello'])
) AS t (arr)
JOIN lateral unnest(t.arr) WITH ORDINALITY AS vals(element, idx) ON TRUE
WHERE vals.idx = ANY(array_positions(array[1,2,1], 1));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...