Синтаксис для цикла функции через элементы массива? - PullRequest
0 голосов
/ 31 декабря 2018

Я впервые пытаюсь создать функцию в Postgres и впервые работаю с массивами.И первый вопрос о Stackoverflow!

Существует двухуровневый числовой массив {{a1,b1},{a2,b2}...{ai,bi}}.Попытка вычислить 3 вещи:

  1. Хотелось бы перебрать и умножить каждый подмассив, т.е. (a1 * b1), а затем накапливать в массиве, пока не будет достигнута определенная цифра (x), то есть (a1 * b1) + (a2 * b2)... + ...(ai * bi) >= x.Таким образом, ai * bi является первым подмассивом, который выдвигает накопление выше x.Я хочу вернуть эту накопленную цифру.

  2. Совокупный b.т. е. (b1 + b2 +...+ bi).

  3. ai.

Вне цикла я хочу выполнить некоторые вычисления, используя эти 3 цифры.

Не удалось включить DO для локализации переменных, но это было бы здорово, если это возможно.

Просмотр около 1M строк.Каждая строка может содержать сотни элементов подмассива в основном массиве, но мне вряд ли понадобится более 8 подмассивов, умноженных и суммированных в строке.

Postgres 9.6.

Я смотрел на foreach и нарезать на массивы, но не уверен, что хорошо использовать в этом случае.Не уверен, что unnest тоже подойдет.В настоящее время нет индексов.

CREATE OR REPLACE FUNCTION accum (numeric[i],numeric[i]) RETURNS numeric AS 
$$

DECLARE
x integer := 100;
y numeric;
z numeric;

BEGIN
  LOOP

-- Accumulate subarray products
  y := SELECT(ANYARRAY)[i:i][1:1]*SELECT(ANYARRAY)[i:i][2:2] + y;

-- Accumulate 2nd element of subarrays
  z := SELECT(ANYARRAY)[i:i][2:2] + z;

EXIT WHEN y > x; 

END LOOP;

RETURN y,
       z,
       -- Return first element of subarray that makes y > x
       SELECT(ANYARRAY)[i:i][1:1];

"Calculation involving output"

END
$$
LANGUAGE plpgsql
;

Я не уверен, как вернуть несколько выходов из цикла.Стремясь получить единый цифровой вывод из этой функции.Любая помощь с синтаксисом или методом, как я собираюсь об этом, будет высоко ценится!Можно ли вообще сделать все это без функции?Спасибо за чтение.

1 Ответ

0 голосов
/ 31 декабря 2018

Многомерный массив в Postgres не так прост для реализации, потому что под-массивы не являются "элементами". Я рекомендую вам использовать тип из (a,b), а затем передатьмассив этого типа.Проще ссылаться на элементы таким образом.

создать тип

create type abtype AS( a numeric, b numeric);

Функция

CREATE OR REPLACE FUNCTION accum (abtyparray abtype[]) RETURNS numeric AS 
$$

DECLARE
x integer := 100;
ab abtype;
y numeric := 0;
z numeric := 0;

BEGIN

   FOREACH ab IN ARRAY abtyparray 
   LOOP
     y := y + ab.a * ab.b; --(a1 * b1) + (a2 * b2)... + ...(ai * bi) 
     z := z + ab.b;  --Cumulative b
     EXIT WHEN y > x; 
   END LOOP;
     RAISE NOTICE 'y = %, z= %,ai = % ', y,z,ab.a;
                                            --^ai
    RETURN y;

END
$$
LANGUAGE plpgsql;

Исполнение

knayak=# DO $$
knayak$# BEGIN
knayak$# PERFORM  accum (ARRAY[(3,4),(10,9),(17,19)] ::abtype[] ) ;
knayak$# END $$;
NOTICE:  y = 102, z= 13,ai = 10
DO

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...