Объединение двух массивов в PostgreSQL в качестве индекса и значения? - PullRequest
2 голосов
/ 01 июля 2011

Предположим, у меня есть два поля массива в таблице, например:

 Column |   Type    |
--------+-----------+
 index  | integer[] | 
 value  | integer[] | 

Где и индекс, и значение равны по длине, а значения в «индексе» гарантированно будут уникальными, например:

SELECT * FROM ArrayTest;
   index   | value             
-----------+-----------------------------------
 {1,3,5,6} | {100, 103, 105, 106}

Как мне сделать запрос, который возвращает новый массив, где значения в 'index' используются в качестве индексов массива, а значения в 'value' становятся значениями, связанными с данным индексом, то есть что-то вроде:

SELECT some_array_function(index, value) as newarray;
            new_array
--------------------------------
{100, NULL, 103, NULL, 105, 106}

То, чего я хочу достичь - это то же самое, что array_combine в PHP.

Ответы [ 2 ]

3 голосов
/ 01 июля 2011

Хотя в целом плохая идея хранить такие данные, один из способов сделать это - использовать функцию unnest и обработать результаты на стороне клиента:

SELECT unnest(index), unnest(value) FROM ArrayTest;

 unnest | unnest 
--------+--------
      1 |    100
      3 |    103
      5 |    105
      6 |    106

Если у вас должна быть функцияЧтобы создать новый массив, вот короткая функция, которая сделает это:

CREATE FUNCTION array_stitch(index_array integer[], value_array integer[]) RETURNS integer[]
    LANGUAGE plpgsql IMMUTABLE
    AS $$
DECLARE
    ptr INTEGER;
    new_array INTEGER[];
BEGIN
    FOR ptr IN 1..array_upper(index_array,1) LOOP
            new_array[index_array[ptr]] := value_array[ptr];
    END LOOP;

    RETURN new_array;
END;
$$;

РЕДАКТИРОВАТЬ: Вот еще один способ сделать это:

SELECT array_agg(val order by idx) as output_array
FROM (SELECT generate_series(1,idx[array_upper(idx,1)]) from array_test) as g(idx)
LEFT JOIN (SELECT unnest(idx) as idx, unnest(val) as val FROM array_test\
    ) as data_points USING (idx);
1 голос
/ 01 июля 2011

Попробуйте эту простую процедуру:

CREATE OR REPLACE FUNCTION merge_arrays(index INTEGER[], value INTEGER[]) RETURNS INTEGER[] AS $$
DECLARE
    arr_size INTEGER;
    max_index INTEGER;
    result INTEGER[];
    i INTEGER;
    index_pos INTEGER := 1;
BEGIN
    arr_size := array_upper(index, 1);
    max_index := index[arr_size];

    FOR i IN 1..max_index LOOP
        IF index @> ARRAY[i] THEN
            result := result || value[index_pos];
            index_pos := index_pos + 1;
        ELSE
            result := result || '{NULL}'::INTEGER[];
        END IF;

    END LOOP;

    RETURN result;
END;
$$ LANGUAGE PLPGSQL;

Использование:

SELECT merge_arrays(index ,value) from array_test;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...