I want to take an array of n dimensions and return set containing rows of arrays of n-1 dimensions. For example, take the array ARRAY[[1,2,3], [4,5,6], [7,8,9]] and return a set {1,2,3}, {4,5,6}, {7,8,9}. Using unnest returns the set 1,2,3,4,5,6,7,8,9.
I tried grabbing the unnest function from PostgreSQL 8.4, which seems like it would do what I’m looking for:
CREATE OR REPLACE FUNCTION tstng.unnest2(anyarray)
RETURNS SETOF anyelement
LANGUAGE plpgsql
IMMUTABLE
AS $$
BEGIN
RETURN QUERY SELECT $1[i]
FROM generate_series(array_lower($1,1), array_upper($1,1)) i;
END;
$$;
However, SELECT tstng.unnest2(ARRAY[[1,2,3], [4,5,6], [7,8,9]]); returns the set , , (i.e.: 3 null rows).
I’ve also found that SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[0]; returns null, which I believe to be the root of my problem.
Function
To break out 1-dimensional arrays from n-dimensional arrays – representing leaves of the nested dimensions. (With n >= 1.)
PL/pgSQL
With a
FORloop looping through the array:SLICE 1instructs to take the 1-dimensonal arrays. (SLICE 2would take 2-dimensional arrays.)PARALLEL SAFEonly for Postgres 9.6 or later.Later tests revealed this PL/pgSQL function to be fastest.
Related:
Pure SQL
Only works for 2D arrays:
This is an improved and simplified version of the function Lukas posted.
db<>fiddle here
Old sqlfiddle
Explanation
returns the same as:
… which is
NULL. The manual:0has no special meaning as array subscript. There’s just nothing there for Postgres arrays with default indexes.Also, with two-dimensional arrays, you need two indexes to get a base element. Like:
Result:
The first part of your message is a bit unclear.
Result:
That’s two dimensions with 3 elements (1 to 3) each (9 base elements).
If you want
n-1dimensions then this is a correct result:Result:
That’s one dimension.
unnest()produces one base element per row (regardless of array dimensions). Your example is just another 2-dimensional array with a missing set of curly brackets … ?If you want a slice of the array:
Result:
Or:
Result:
To flatten the result (get a 1D array):
Read the manual here.
For very old versions
For Postgres versions < 8.4,
array_agg()is not installed by default. Create it first:Also,
generate_subscripts()is not born, yet. Use instead:Call:
Result