PostgreSQL gør leverer dedikerede funktioner til at generere array-underskrifter:
WITH x(a) AS ( VALUES ('{1,20,3,5}'::int[]) )
SELECT generate_subscripts(a, 1) AS idx
,unnest(a) AS val
FROM x;
Effektivt gør det næsten det samme som @Franks forespørgsel, bare uden underforespørgsel.
Plus det virker med sænkede numre, der ikke starter med 1
.
Begge løsninger fungerer for 1-dimensionelle kun arrays! (Kan nemt udvides til flere 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 til:
SELECT * FROM unnest_with_idx('{1,20,3,5}'::int[]);
Overvej også:
SELECT * FROM unnest_with_idx('[4:7]={1,20,3,5}'::int[]);
Mere om array-subscripts i dette relaterede spørgsmål.
Hvis du faktisk vil have normaliserede abonnenter (startende med 1), vil jeg bruge:
SELECT generate_series(1, array_length($1,1)) ...
Det er næsten den forespørgsel, du allerede havde, bare med array_length()
i stedet for array_upper()
- hvilket ville mislykkes med ikke-standard abonnementer.
Ydeevne
Jeg kørte en hurtig test på et array på 1000 int med alle forespørgsler præsenteret her indtil videre. De udfører alle omtrent det samme (~ 3,5 ms) - undtagen row_number()
på en underforespørgsel (~ 7,5 ms) - som forventet på grund af underforespørgslen.
Opdatering:Postgres 9.4+
Medmindre du arbejder med ikke-standardiserede indekser, skal du bruge den nye WITH ORDINALITY
i stedet:
- PostgreSQL unnest() med elementnummer