并行取消嵌套多个数组
Posted
技术标签:
【中文标题】并行取消嵌套多个数组【英文标题】:Unnest multiple arrays in parallel 【发布时间】:2015-03-06 08:44:05 【问题描述】:我的最后一个问题Passing an array to stored to postgres 有点不清楚。现在,澄清我的目标:
我想创建一个接受两个输入参数的 Postgres 存储过程。一个是一些金额的列表,例如(100, 40.5, 76)
,另一个是一些发票 ('01-2222-05','01-3333-04','01-4444-08')
的列表。之后,我想使用这两个数字和字符列表并用它们做一些事情。例如,我想从这个数字数组中取出每个金额并将其分配给相应的发票。
Oracle 中的类似内容如下所示:
SOME_PACKAGE.SOME_PROCEDURE (
789,
SYSDATE,
SIMPLEARRAYTYPE ('01-2222-05','01-3333-04','01-4444-08'),
NUMBER_TABLE (100,40.5,76),
'EUR',
1,
P_CODE,
P_MESSAGE);
当然,SIMPLEARRAYTYPE
和 NUMBER_TABLE
这两种类型在前面的 DB 中已经定义好了。
【问题讨论】:
究竟有什么不清楚的地方?如何调用这些函数?您可以使用数组构造函数 postgresql.org/docs/current/static/… 或者,您可以将它们的输入表示形式写入字符串(然后可选地使用强制转换)postgresql.org/docs/current/static/arrays.html#ARRAYS-IO 我不知道如何使用这些输入参数创建存储过程。 这也包含在您之前的问题中(例如 ***.com/questions/27708234/… )——您可以使用标准兼容的<type> ARRAY
或 PostgreSQL 特定的 <type>[]
语法。 postgresql.org/docs/current/static/…
【参考方案1】:
通过将[]
添加到基本数据类型来声明数组。将它们声明为参数的方式与声明常规参数的方式相同:
以下函数接受整数数组和字符串数组,并返回一些虚拟文本:
create function array_demo(p_data integer[], p_invoices text[])
returns text
as
$$
select p_data[1] || ' => ' || p_invoices[1];
$$
language sql;
select array_demo(array[1,2,3], array['one', 'two', 'three']);
SQLFiddle 演示:http://sqlfiddle.com/#!15/fdb8d/1
【讨论】:
对不起,我的错,没关系。你可以在文本数组上使用 FOREACH 吗? 我可以在 Postgres 中对文本数组使用 FOREACH 吗? @Maki:如果一切都失败了,请阅读手册:postgresql.org/docs/current/static/…【参考方案2】:你会喜欢 Postgres 9.4的这个新功能:
<b>unnest(anyarray, anyarray [, ...])</b>
unnest()
具有非常期待(至少在我看来)能够并行干净地取消嵌套多个数组的能力。 The manual:
将多个数组(可能是不同类型的)扩展为一组行。这只允许在 FROM 子句中;
这是新的ROWS FROM
feature 的特殊实现。
你的函数现在可以是:
CREATE OR REPLACE FUNCTION multi_unnest(_some_id int
, _amounts numeric[]
, _invoices text[])
RETURNS TABLE (some_id int, amount numeric, invoice text) AS
$func$
SELECT _some_id, u.* FROM unnest(_amounts, _invoices) u;
$func$ LANGUAGE sql;
呼叫:
SELECT * FROM multi_unnest(123, '100, 40.5, 76'::numeric[]
, '01-2222-05,01-3333-04,01-4444-08'::text[]);
当然,简单的形式也可以换成plain SQL(无附加功能):
SELECT 123 AS some_id, *
FROM unnest('100, 40.5, 76'::numeric[]
, '01-2222-05,01-3333-04,01-4444-08'::text[]) AS u(amount, invoice);
在早期版本(Postgres 9.3-)中,您可以使用不太优雅和不太安全的形式:
SELECT 123 AS some_id
, unnest('100, 40.5, 76'::numeric[]) AS amount
, unnest('01-2222-05,01-3333-04,01-4444-08'::text[]) AS invoice;
旧速记形式的注意事项:除了在SELECT
列表中设置返回函数是不标准的,返回的行数将是每个数组元素数的最小公倍数(结果令人惊讶不等数)。这些相关答案中的详细信息:
这种行为终于被 Postgres 10 清除了。 SELECT
列表中的多个集合返回函数现在以“锁步”方式生成行。见:
【讨论】:
文档中关于“rows from”语法的文档有点混乱,没有示例。仅供参考,select * from rows from(unnest('1,2,3'::integer[]), unnest('4,5,6'::integer[]), unnest('7,8'::integer[])) u(a, b, c);
将演示基本用法——“rows from”构造返回一个可在 from 子句中使用的表。以上是关于并行取消嵌套多个数组的主要内容,如果未能解决你的问题,请参考以下文章
BigQuery - 如何取消嵌套多个数组,并从一列分配值?