sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur får man åtkomst till array internt index med postgreSQL?

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


  1. SQL Server:dynamisk pivot över 5 kolumner

  2. Oracle RAC N+1 Redundans

  3. Konvertera ett månadsnummer till månadsnamnet i SQL Server (T-SQL)

  4. SQLSTATE[42000]:Syntaxfel eller åtkomstöverträdelse:1064 Du har ett fel i din SQL-syntax — PHP — PDO