PostgreSQL fait fournissent des fonctions dédiées pour générer des indices de tableau :
WITH x(a) AS ( VALUES ('{1,20,3,5}'::int[]) )
SELECT generate_subscripts(a, 1) AS idx
,unnest(a) AS val
FROM x;
En fait, cela fait presque la même chose que la requête de @Frank, mais sans sous-requête.
De plus, cela fonctionne avec des indices qui ne commencent pas par 1
.
L'une ou l'autre solution fonctionne pour 1-dimensionnel tableaux uniquement ! (Peut facilement être étendu à plusieurs dimensions.)
Fonction :
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$;
Appel :
SELECT * FROM unnest_with_idx('{1,20,3,5}'::int[]);
Considérez également :
SELECT * FROM unnest_with_idx('[4:7]={1,20,3,5}'::int[]);
Plus d'informations sur les indices de tableau dans cette question connexe.
Si vous voulez en fait des indices normalisés (commençant par 1), j'utiliserais :
SELECT generate_series(1, array_length($1,1)) ...
C'est presque la requête que vous aviez déjà, juste avec array_length()
au lieu de array_upper()
- qui échouerait avec des indices non standard.
Performances
J'ai effectué un test rapide sur un tableau de 1000 int avec toutes les requêtes présentées ici jusqu'à présent. Ils fonctionnent tous à peu près de la même manière (~ 3,5 ms) - à l'exception de row_number()
sur une sous-requête (~ 7,5 ms) - comme prévu, à cause de la sous-requête.
Mise à jour :Postgres 9.4+
Sauf si vous travaillez avec des indices d'index non standard, utilisez le nouveau WITH ORDINALITY
à la place :
- PostgreSQL unnest() avec le numéro d'élément