PostgreSQL: concatenate nested arrays with differing element dimensions - arrays

Concatenating the nested arrays {{1,2}} and {{3,4}} is no problem at all:
SELECT array_cat(
ARRAY[ARRAY[1,2]]
, ARRAY[ARRAY[3,4]]
)
array_cat
---------------
{{1,2},{3,4}}
But how to concatenate {{1,2}} and {{3}} in order to get {{1,2},{3}}?
SELECT array_cat(
ARRAY[ARRAY[1,2]]
, ARRAY[ARRAY[3]]
)
psql: …: ERROR: cannot concatenate incompatible arrays
DETAIL: Arrays with differing element dimensions are not compatible
for concatenation.

This is impossible in PostgreSQL. Multi-dimensional arrays must have the same number of element dimensions, just as the error message informs. Per documentation:
Multidimensional arrays must have matching extents for each dimension. A mismatch causes an error.
You might want to pad with NULL or some other dummy value ...

Related

Error using horzcat Dimensions of arrays being concatenated are not consistent. Matlab

I am geting the Error using horzcat
Dimensions of arrays being concatenated are not consistent.
I am trying to do the following:
Y = [single(time)' Bmag' Br' Bt' Bn']
However, my arrays are of the same size:
Your time array is 1x3060 instead of 1x3600.

Select records where two arrays are not equal regardless of the order of the array elements in PySpark

How to select records where two arrays are not equal regardless of the order of the array elements using PySpark?
Use array_sort to sort the arrays first:
import pyspark.sql.functions as F
df.filter(F.array_sort(F.col('array1')) != F.array_sort(F.col('array2')))

Array subtraction in Google Sheets

I have two arrays and I want a resulting array that's the vector difference.
A1:A10 and B1:B10 have numeric values, and I want {A1:A10}-{B1:B10}, but that just gives me A1-B1, not the full array. Is there a subtraction operator for arrays?
Example Sheet:
https://docs.google.com/spreadsheets/d/1rjh_mkpZdz7LX4V0obxEmfRLdZ2CoTIjdpxVLHYBD5s/edit#gid=0
I want the result in D1 without the extra column C
use ArrayFormula:
=ARRAYFORMULA(A1:A10-B1:B10)
or shorter Index:
=INDEX(A1:A10-B1:B10)
or longer Query:
=QUERY(A1:B10, "select A-B label A-B''", 0)

PostgreSQL multidimensional arrays

I'm trying to pass data around as a multidimensional array, and I'm getting behavior that seems odd to me. Specifically I'm trying to get a single element out of a 2 dimensional array (so a 1 dimensional array out of my 2 dimension array), and it doesn't work the way I'd expect.
In the following examples #2, 4, & 5 work the way I'd expect, but 1 & 3 do not.
db=> select s.col[2] from (select array[[1,2,3],[4,5,6]] as col) s;
col
-----
(1 row)
db=> select s.col[2:2] from (select array[[1,2,3],[4,5,6]] as col) s;
col
-----
{{4,5,6}}
(1 row)
db=> select array[s.col[2]] from (select array[[1,2,3],[4,5,6]] as col) s;
array
--------
{NULL}
(1 row)
db=> select array[s.col[2:2]] from (select array[[1,2,3],[4,5,6]] as col) s;
array
-------------
{{{4,5,6}}}
(1 row)
db=> select s.col[2][1] from (select array[[1,2,3],[4,5,6]] as col) s;
col
-----
4
(1 row)
Is there doc on this? I have something that's working well enough for me right now, but it's ugly and I worry it won't do the things I want to do next. Technically I'm getting a 2 dimensional array, where 1 dimension only has 1 element. I'd rather just get an array.
I've read (among others):
http://www.postgresql.org/docs/9.1/static/arrays.html
http://www.postgresql.org/docs/9.1/static/functions-array.html
http://www.postgresql.org/docs/9.1/static/sql-expressions.html#SQL-SYNTAX-ARRAY-CONSTRUCTORS
And I'm just not seeing what I'm looking for.
Postgres array elements are always base elements, i.e. non-array types. Sub-arrays are not "elements" in Postgres. Array slices retain original dimensions.
You can either extract a base element, with element data type. Or you can extract an array slice, which retains the original array data type, and also original array dimensions.
Your idea to retrieve a sub-array as "element" would conflict with that and is just not implemented.
The manual might be made clearer in its explanation. But at least we can find:
If any dimension is written as a slice, i.e., contains a colon, then
all dimensions are treated as slices. Any dimension that has only a
single number (no colon) is treated as being from 1 to the number
specified. For example, [2] is treated as [1:2] ...
Your 1st example tries to reference a base element, which is not found (you'd need a subscript with two array indexes in a 2D array). So Postgres returns NULL.
Your 3rd example just wraps the resulting NULL in a new array.
To flatten an array slice (make it a 1D array) you can unnest() and feed the resulting set to a new ARRAY constructor. Either in a correlated subquery or in a LATERAL join (requires pg 9.3+). Demonstrating both:
SELECT s.col[2:2][2:3] AS slice_arr
, x.lateral_arr
, ARRAY(SELECT unnest(s.col[2:2][2:3])) AS corr_arr
FROM (SELECT ARRAY[[1,2,3],[4,5,6]] AS col) s
, LATERAL (
SELECT ARRAY(SELECT * FROM unnest(s.col[2:2][2:3])) AS lateral_arr
) x;
Be sure to read the current version of the manual. your references point to Postgres 9.1, but chances are you are actually using Postgres 9.4.
Related:
How to select 1d array from 2d array?
Unnest array by one level

How to get the last element of an array in PostgreSQL?

The PostgreSQL Documentation on arrays provides an example using [-1] to access what appears to be the last element of an array; however while SELECT arr[2:3]; produces {5,9}, arr[2:-1] results in {}.
How can the last element of an array be obtained in PostgreSQL?
Edit: Windows, PostgreSQL v9.2.1
For any array "arr", to fetch the last element of array arr use
SELECT arr[array_upper(arr, 1)];
I think you're misinterpreting the example. PostgreSQL arrays don't have to be indexed from 1 to n, that's just the default:
By default PostgreSQL uses a one-based numbering convention for arrays, that is, an array of n elements starts with array[1] and ends with array[n].
The example you're looking at is this:
SELECT f1[1][-2][3] AS e1, f1[1][-1][5] AS e2
FROM (SELECT '[1:1][-2:-1][3:5]={{{1,2,3},{4,5,6}}}'::int[] AS f1) AS ss;
But those negative numbers aren't indexing from the end of the arrays as in languages such as Perl. In the FROM (SELECT ... part, they're specifying the starting and ending indexes so the -1 in f1[1][-1][5] is just a plain old index. Consider this array_dims result:
=> SELECT array_dims('[1:1][-2:-1][3:5]={{{1,2,3},{4,5,6}}}'::int[]);
array_dims
-------------------
[1:1][-2:-1][3:5]
If you're using the default 1-based arrays then you can get the last element with a simple arr[array_length(arr, 1)]. If you're not using the default [1:n] arrays then you'll have to mess around with array_lower and array_upper to get the first and last elements; or, depending on the circumstances, you might be able to use unnest to unpack the array then work with the array as a rowset.
If someone is using Postgre 9.5, the documentation says:
-> int
Get JSON array element (indexed from zero, negative integers count from the end)
So this works for me:
to_json(arr)->-1

Resources