如果可能的话,我想将这些数据作为位图存储在一个字节中。以下是如何获取一系列字节值并将其转换为字节茶:
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 中的二维数组有些奇怪,但您正在尝试做的事情也是如此。