PostgreSQL:将表值函数串行应用于一组值和 UNION ALL 结果
Posted
技术标签:
【中文标题】PostgreSQL:将表值函数串行应用于一组值和 UNION ALL 结果【英文标题】:PostgreSQL: Serially apply table-valued function to a set of values and UNION ALL results 【发布时间】:2013-08-21 15:22:29 【问题描述】:我有一个表值 PL/pgsql 函数,它将一个整数、一个 ID 作为 1 输入。返回的表具有固定列(例如 5),但行数不同。
有一张包含这些唯一 ID 的大表。我想将此函数应用于每个 ID 并 UNION ALL 结果。
在网上看,我一直看到 CROSS APPLY 作为解决方案,但它似乎在 PostgreSQL 中不可用。我该如何做这个“应用”操作?
一个简单的解决方案是用一个额外的外循环重写表值函数。但是有没有办法直接在 SQL 中做到这一点?
【问题讨论】:
使用当前的 Postgres(9.2 或更低版本),您可以将 ID 表直接集成到返回单个集合的表函数中,而不是循环。重新思考逻辑可能很难,但根据我的经验,通常可以做到。 【参考方案1】:我认为在当前版本的 PostgreSQL (9.2) 中是不可能的。在 9.3 中,LATERAL join 将完全符合您的要求。
不过,您可以 apply
函数返回一组简单值:
select id, func(id) as f from tbl1
sql fiddle demo
【讨论】:
【参考方案2】:SQL Fiddle
create table t (id int);
insert into t (id) select generate_series(1, 10);
create or replace function f (i integer)
returns table(id_2 integer, id_3 integer) as $$
select id * 2 as id_2, id * 3 as id_3
from t
where id between i - 1 and i + 1
$$ language sql;
select id, (f(id)).*
from t;
【讨论】:
虽然看起来它在做 OP 想要的,但实际上并非如此。此语句为每一列调用 f(id),因此结果可能令人惊讶,请参阅 sqlfiddle - sqlfiddle.com/#!12/54d98/2。 @Roman 这与问题无关。检查这些查询:sqlfiddle.com/#!12/54d98/9 如果您在机器上运行第二个查询,您会对 clock_timestamp 结果感到惊讶。 @Roman 我的意思是,虽然 random() 序列总是会产生相同的结果,但不可能(据我所知)预测 Postgresql 将以什么顺序执行这些 random( ),即顺序可以与字面查询顺序不同。 我试图测试的是实际调用函数的次数。我认为,如果每个 ID 都处于待命状态,则应该有第二行中的 id2 等于第一行中的 id3 的行,反之亦然,并且该条件不成立 => 我认为每个列都会调用该函数 - sqlfiddle.com/#!12/54d98/13 @Roman 当你说select (f(id)).id_1, (f(id)).id_2
将调用该函数两次时,你是对的(我猜)。但是正如我在之前的 cmets 中所展示的那样,您的测试是错误的。我不敢相信select (f(id)).*
会不止一次调用它。 sqlfiddle.com/#!12/3b815/1以上是关于PostgreSQL:将表值函数串行应用于一组值和 UNION ALL 结果的主要内容,如果未能解决你的问题,请参考以下文章