sql >> Database teknologi >  >> RDS >> PostgreSQL

Hvordan får man adgang til array internt indeks med postgreSQL?

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


  1. Den flerdelte identifikator kunne ikke bindes

  2. Implementering og administration af PostgreSQL 11:Nyt i ClusterControl 1.7.1

  3. Hvordan skriver man IF ELSE-sætning i en MySQL-forespørgsel

  4. SQL WHERE-erklæring