10

I have 2d array and want to select only first element of it, which is 1d array.
How do I do that?

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
thecoparyew
  • 715
  • 1
  • 9
  • 24
  • Near-duplicate of http://stackoverflow.com/q/8137112/398670 or http://stackoverflow.com/q/14743097/398670 – Craig Ringer Sep 23 '14 at 13:28
  • You can get a *slice* of the 2D array, but it's still 2D, just one dimension is flat. E.g. `SELECT (ARRAY [ ARRAY[1,2], ARRAY[3,4] ])[1:1];` – Craig Ringer Sep 23 '14 at 13:29

1 Answers1

17

To get the first slice of an array:

SELECT my_arr[1:1];

The resulting array has the same array dimensions as the input.
Details in my previous answer here:

To flatten the result:

SELECT ARRAY(SELECT unnest(my_arr[1:1]));

Or cleaner:

SELECT ARRAY(SELECT * FROM unnest(my_arr)[1:1]));

Examples

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[1:1];

Result:

{{1,2,3}}  -- 2D array

Or:

SELECT ARRAY(
   SELECT unnest((ARRAY[[1,2,3], [4,5,6], [7,8,9]])[1:1])
   );

Result:

{1,2,3}  -- 1D array

Emulate unnest() in Postgres 8.3

The Wiki page you are linking to was a bit misleading. I updated it with code for 2-dimensional arrays.

unnest() for 1-dimensional array:

CREATE OR REPLACE FUNCTION unnest_1d(anyarray)
  RETURNS SETOF anyelement
  LANGUAGE sql IMMUTABLE AS
$func$
SELECT $1[i]
FROM   generate_series(array_lower($1,1), array_upper($1,1)) i
$func$;

unnest() for 2-dimensional array:

CREATE OR REPLACE FUNCTION unnest_2d(anyarray)
  RETURNS SETOF anyelement
  LANGUAGE sql IMMUTABLE AS
$func$
SELECT $1[d1][d2]
FROM   generate_series(array_lower($1,1), array_upper($1,1)) d1
    ,  generate_series(array_lower($1,2), array_upper($1,2)) d2
$func$;

The aggregate function array_agg() is not installed by default in Postgres 8.3:

CREATE AGGREGATE array_agg(anyelement) (
 SFUNC = array_append,
 STYPE = anyarray,
 INITCOND = '{}'
);

Unnest 2d array to 1d arrays:

CREATE OR REPLACE FUNCTION unnest_2d_1d(anyarray)
  RETURNS SETOF anyarray
  LANGUAGE sql IMMUTABLE AS
$func$
SELECT array_agg($1[d1][d2])
FROM   generate_series(array_lower($1,1), array_upper($1,1)) d1
    ,  generate_series(array_lower($1,2), array_upper($1,2)) d2
GROUP  BY d1
ORDER  BY d1
$func$;

fiddle
Old sqlfiddle

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • I wanted 1d array because version of postgres I work on is pretty old (8.3) and there aren't unnest function. So I created function by this link https://wiki.postgresql.org/wiki/Array_Unnest but it is not working for 2d array. With 1d array it works fine. – thecoparyew Sep 23 '14 at 16:57
  • 1
    @thecoparyew: That information should be in your question to begin with. I updated the misleading Wiki page and added some more to the answer. The other option is to upgrade to a current version of Postgres. [Version 8.3 has reached EOL in Feb. 2013.](http://www.postgresql.org/support/versioning/) – Erwin Brandstetter Sep 23 '14 at 19:31
  • 1
    To be didactic, more one information to reader: how to select de second or Nth item (line of the matrix)? Answer: by slices `x[n:n]`... but with the same ugly problem, that the slice od 2D is not 1D, is also 2D. – Peter Krauss May 25 '19 at 18:25