PostgreSQL прави предоставя специални функции за генериране на индекси на масив:
WITH x(a) AS ( VALUES ('{1,20,3,5}'::int[]) )
SELECT generate_subscripts(a, 1) AS idx
,unnest(a) AS val
FROM x;
На практика той прави почти същото като заявката на @Frank, само без подзаявка.
Освен това работи с индекси, които не започват с 1
.
Всяко решение работи за 1-измерни само масиви! (Може лесно да се разшири до множество измерения.)
Функция:
CREATE OR REPLACE FUNCTION unnest_with_idx(anyarray)
RETURNS TABLE(idx integer, val anyelement) LANGUAGE SQL IMMUTABLE AS
$func$
SELECT generate_subscripts($1, 1), unnest($1);
$func$;
Обадете се:
SELECT * FROM unnest_with_idx('{1,20,3,5}'::int[]);
Също така имайте предвид:
SELECT * FROM unnest_with_idx('[4:7]={1,20,3,5}'::int[]);
Повече за индексите на масива в този свързан въпрос.
Ако всъщност искате нормализирани индекси (започвайки с 1), бих използвал:
SELECT generate_series(1, array_length($1,1)) ...
Това е почти заявката, която вече имахте, само с array_length()
вместо array_upper()
- което би се провалило с нестандартни индекси.
Ефективност
Проведох бърз тест върху масив от 1000 int с всички заявки, представени тук досега. Всички те работят приблизително еднакво (~ 3,5 ms) - с изключение на row_number()
на подзаявка (~ 7,5 ms) - както се очаква, поради подзаявката.
Актуализация:Postgres 9.4+
Освен ако не работите с нестандартни индексни индекси, използвайте новия WITH ORDINALITY
вместо това:
- PostgreSQL unnest() с номер на елемент