Home > Blockchain >  Sum of two array subsets
Sum of two array subsets

Time:05-19

I am new to postgres arrays.

I need to modify the first 4 elements of C arrays

The formulas is C[1:4] = A[1:4] B[1:4] This calculation is done over group_name dimension

Is there an elegant way of doing this, maybe without joins?

insert into the_table values
(1,'group 1', 'A', '{1,2,3,4,5}'), 
(2,'group 1', 'B', '{10,20,30,40,50}'),
(3,'group 2', 'A', '{-1,-2,-3,-4,-5}'), 
(4,'group 2', 'B', '{-10,-20,-30,-40,-50}'),
(5,'group 1', 'C', '{0,0,0,0,0}'), 
(6,'group 2', 'C', '{0,0,0,0,0}');

Input data:

id group_name var val
1 group 1 A 1,2,3,4,5
2 group 1 B 10,20,30,40,50
3 group 1 C 0,0,0,0,0
4 group 2 A -1,-2,-3,-4,-5
5 group 2 B -10,-20,-30,-40,-50
6 group 2 C 0,0,0,0,0

Output data:

id group_name var val
1 group 1 A 1,2,3,4,5
2 group 1 B 10,20,30,40,50
3 group 1 C 11,22,33,44,0
4 group 2 A -1,-2,-3,-4,-5
5 group 2 B -10,-20,-30,-40,-50
6 group 2 C -11,-22,-33,-44,0

CodePudding user response:

You need a function that sums arrays on a given basis.

create or replace function sum_arrays(arr int[])
returns int[] language sql immutable as $$
    select array[
        arr[1][1]  arr[2][1],
        arr[1][2]  arr[2][2],
        arr[1][3]  arr[2][3],
        arr[1][4]  arr[2][4],
        0]
$$;

With this function the update looks quite elegant:

update the_table t
set val = sum_arrays
from (
    select group_name, sum_arrays(array_agg(val))
    from the_table
    where var in ('A', 'B')
    group by group_name
) s
where t.group_name = s.group_name
and t.var = 'C';

Test it in db<>fiddle.

CodePudding user response:

There are no piecewise operations on arrays in Postgres. You won't get around a few joins that unnest the arrays, join by index, and aggregate them back:

UPDATE the_table tab_c
SET val = (
  SELECT array_agg(a   b ORDER BY a_idx)
  FROM the_table tab_a,
  unnest(tab_a.val) WITH ORDINALITY AS val_a(a, a_idx),
  the_table tab_b,
  unnest(tab_b.val) WITH ORDINALITY AS val_b(b, b_idx)
  WHERE tab_a.group_name = tab_c.group_name
    AND tab_a.var = 'A'
    AND tab_b.group_name = tab_c.group_name
    AND tab_b.var = 'B'
    AND a_idx = b_idx
)
WHERE tab_c.var = 'C';
TABLE the_table;

(online demo)

  • Related