现在,要回答评论中揭示的真正问题,这似乎是:
给定两个数组“a”和“b”,我如何将它们的元素配对,以便我可以将元素对作为查询中的列别名?
有几种方法可以解决这个问题:
当且仅当数组长度相等时,unnest
在SELECT
子句中使用多个函数(一种已弃用的方法,仅应用于向后兼容);
用于generate_subscripts
遍历数组;
如果您需要支持太旧而无法拥有的版本,请使用generate_series
过度子查询来模拟array_lower
和模拟;array_upper
generate_subscripts
generate_subscripts
依靠unnest
返回元组的顺序并希望 - 就像我的其他答案一样,如下所示。它会工作,但不能保证在未来的版本中工作。
使用PostgreSQL 9.4 中添加的WITH ORDINALITY
功能(另请参阅它的第一篇文章)来获取unnest
9.4 何时发布的行号。
使用 multiple-array UNNEST
,这是 SQL 标准但PostgreSQL 还不支持。
所以,假设我们有arraypair
带有数组参数的函数a
和b
:
CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
-- blah code here blah
$$ LANGUAGE whatever IMMUTABLE;
它被调用为:
SELECT * FROM arraypair( ARRAY[1,2,3,4,5,6,7], ARRAY['a','b','c','d','e','f','g'] );
可能的函数定义是:
SRF-in- SELECT
(已弃用)
CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
SELECT unnest(a), unnest(b);
$$ LANGUAGE sql IMMUTABLE;
如果数组长度不相等,将产生奇怪和意想不到的结果;请参阅列表中有关集合返回函数及其非标准用法的文档,SELECT
以了解原因以及究竟发生了什么。
generate_subscripts
这可能是最安全的选择:
CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
SELECT
a[i], b[i]
FROM generate_subscripts(CASE WHEN array_length(a,1) >= array_length(b,1) THEN a::text[] ELSE b::text[] END, 1) i;
$$ LANGUAGE sql IMMUTABLE;
如果数组的长度不相等,如所写,它将返回较短的空元素,因此它的工作方式类似于完全外连接。反转大小写的意义以获得类似内部连接的效果。该函数假定数组是一维的,并且它们从索引 1 开始。如果整个数组参数为 NULL,则该函数返回 NULL。
更通用的版本将用 PL/PgSQL 编写,并会检查array_ndims(a) = 1
、检查array_lower(a, 1) = 1
、测试空数组等。我将把它留给你。
希望成对回报:
这不能保证有效,但对 PostgreSQL 的当前查询执行器有效:
CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
WITH
rn_c1(rn, col) AS (
SELECT row_number() OVER (), c1.col
FROM unnest(a) c1(col)
),
rn_c2(rn, col) AS (
SELECT row_number() OVER (), c2.col
FROM unnest(b) c2(col)
)
SELECT
rn_c1.col AS c1,
rn_c2.col AS c2
FROM rn_c1
INNER JOIN rn_c2 ON (rn_c1.rn = rn_c2.rn);
$$ LANGUAGE sql IMMUTABLE;
我会考虑使用generate_subscripts
更安全。
多参数unnest
:
这应该可以工作,但不能,因为 PostgreSQLunnest
不接受多个输入数组(还):
SELECT * FROM unnest(a,b);