PostgreSQL gör tillhandahålla dedikerade funktioner för att generera array-subskript:
WITH x(a) AS ( VALUES ('{1,20,3,5}'::int[]) )
SELECT generate_subscripts(a, 1) AS idx
,unnest(a) AS val
FROM x;
I praktiken gör den nästan samma sak som @Franks fråga, bara utan subquery.
Pluss den fungerar med subscripts som inte börjar med 1
.
Båda lösningarna fungerar för 1-dimensionell bara arrayer! (Kan enkelt utökas till flera dimensioner.)
Funktion:
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$;
Ring:
SELECT * FROM unnest_with_idx('{1,20,3,5}'::int[]);
Tänk också på:
SELECT * FROM unnest_with_idx('[4:7]={1,20,3,5}'::int[]);
Mer om arraysubscripts i den här relaterade frågan.
Om om du faktiskt vill ha normaliserade prenumerationer (som börjar med 1), skulle jag använda:
SELECT generate_series(1, array_length($1,1)) ...
Det är nästan den fråga du redan hade, bara med array_length()
istället för array_upper()
- vilket skulle misslyckas med icke-standardiserade prenumerationer.
Prestanda
Jag körde ett snabbtest på en array av 1000 int med alla frågor som presenterats här hittills. De presterar alla ungefär likadant (~ 3,5 ms) - förutom row_number()
på en underfråga (~ 7,5 ms) - som förväntat, på grund av underfrågan.
Uppdatering:Postgres 9.4+
Såvida du inte arbetar med icke-standardiserade indexnedteckningar, använd den nya WITH ORDINALITY
istället:
- PostgreSQL unnest() med elementnummer