Я хотел бы сохранить эти данные в виде растрового изображения в байтах, если это возможно. Вот как взять ряд байтовых значений и превратить его в bytea:
WITH bytes(b) AS (SELECT x % 256 FROM generate_series(1,53000) x)
SELECT ('\x'||string_agg(lpad(to_hex(b),2,'0'),''))::bytea FROM bytes;
Вы можете получить доступ к полям или диапазонам массива байтов, используя функцию substr. Этот bytea организован как линейный массив пикселей, но вы можете найти более полезным организовать его в более традиционный формат растрового изображения. Кроме того, если ваши пиксели состоят из более чем одного байта, вам может потребоваться справиться с обратным порядком байтов и прямым порядком байтов. Вы можете сделать это в SQL, но, вероятно, это будет намного проще в процедурном языке, таком как PL/Perl.
В противном случае разумным выбором будет многомерный массив.
Используя оператор generate_series вместо поля pix_val для удобного тестирования, этот запрос создает двумерный массив целых чисел с использованием двух проходов агрегирования:
SELECT ('{'||string_agg(subarray, ',')||'}')::integer[] AS arr
FROM (
SELECT array_agg(x order by x)::text
FROM generate_series(1,53000) x
GROUP BY width_bucket(x, 1, 53001, 100)
) a(subarray);
Неудачное использование формы строкового литерала двумерного массива необходимо из-за того факта, что array_agg не может агрегировать массивы. На мой взгляд, это настоящая проблема PostgreSQL; в общем, его многомерные массивы непривычны для работы и несовместимы с тем, как большинство приложений и языков реализуют массивы.
Вы можете получить поля из массива, проиндексировав его. Пример:
regress=> SELECT ('{'||string_agg(subarray, ',')||'}')::integer[] AS arr INTO test FROM (SELECT array_agg(x order by x)::text from generate_series(1,53000) x GROUP BY width_bucket(x, 1, 53001, 100)) a(subarray);
regress=> \d test
Table "public.test"
Column | Type | Modifiers
--------+-----------+-----------
arr | integer[] |
test содержит один массив с двумя измерениями:
regress=> \x
regress=> select array_dims(test.arr), array_ndims(test.arr), array_length(test.arr,1), array_length(test.arr,2) FROM test;
-[ RECORD 1 ]+---------------
array_dims | [1:100][1:530]
array_ndims | 2
array_length | 100
array_length | 530
Я могу получить элементы с двухуровневой индексацией:
regress=> SELECT test.arr[4][4] FROM test;
arr
------
1594
(1 row)
или «столбец» с нарезкой:
regress=> SELECT test.arr[4:4][1:530] FROM test;
Как ни странно, это по-прежнему двумерный массив, верхнее измерение имеет глубину всего в один элемент. Вы можете сгладить его (неэффективно) с помощью unnest и array_agg, если вам нужно.
Двумерные массивы в PostgreSQL, как видите, несколько странны, но именно это вы и пытаетесь сделать.
person
Craig Ringer
schedule
31.10.2012
pix_val, тогда вы можете использоватьcrosstab. В противном случае вы можете использоватьarray_aggдля получения массиваpix_val. - person Craig Ringer   schedule 31.10.2012byteaи сохранить как массив байтов. Если вы должны иметь его в SQL, используйте двумерный массив. - person Craig Ringer   schedule 31.10.2012