PostgreSQL:重用适用于虚拟表数据的函数代码
Posted
技术标签:
【中文标题】PostgreSQL:重用适用于虚拟表数据的函数代码【英文标题】:PostgreSQL: Reuse function code that works on virtual table data 【发布时间】:2015-07-04 19:46:15 【问题描述】:我的代码适用于 3 列 (id | timestamp | value
) 的数据集(= 多行)并产生单个数值结果(分数)。
现在我想把这段代码放在一个函数中,以便我可以重用它。假设我有 4 个其他查询都生成具有这 3 个列的数据集,我想从中计算 score,而无需复制/粘贴我的代码......我该怎么做?似乎无法将 TABLE(...)
类型作为函数参数传递。
我认为我不能使用聚合函数,因为我的评分代码会在内部添加新行、对它们进行分组等等。我需要同时处理所有行并且没有状态转换。
【问题讨论】:
什么是“虚拟表”?你的意思是一个表函数(“设置返回函数”)?请显示您的功能代码(或简化示例)并详细说明want to reuse my scoring code
。您需要更具体地说明您想要做什么。 Postgres 没有表变量,还有其他方法...
请编辑问题,而不是将太多重要信息放入 cmets。不是那个地方。
那么请给我们看一下你的函数代码
那么当你说“我有代码适用于数据集”时,你指的是哪个代码?那个代码在哪里?它现在在做什么?
如果您不显示要通过动态输入重用的代码,我们将无法帮助您。如果您的函数过于复杂,请提供一个简化示例来展示基本原理。听起来你需要dynamic SQL。
【参考方案1】:
这个问题很有趣,因为它引发了对自定义聚合函数的非标准使用的反思。
(...) 想象一些查询首先按 id 对行进行排序,然后相乘 第一个 row.value 的值为 4th,并将其设置为新的 第一行的值。然后它返回第一个
我们需要:
作为聚合的自定义复合类型对特定类型的值进行操作, 状态转换函数,将连续行保存在临时表中, final 函数,执行计算并返回最终结果。create type scores as (id int, val numeric);
create function save_scores(p scores, n scores)
returns scores language plpgsql as $$
begin
if p is null then
create temp table temp_scores of scores;
end if;
insert into temp_scores values (n.id, n.val);
return n;
end $$;
create function calculate_scores(t scores)
returns numeric language plpgsql as $$
declare
id1 int;
val4 numeric;
res numeric;
begin
select id into id1 from temp_scores order by id limit 1;
select val into val4 from temp_scores order by id offset 3 limit 1;
update temp_scores set val = val* val4 where id = id1;
select val into res from temp_scores where val < 5 order by id limit 1;
drop table temp_scores;
return res;
end $$;
聚合:
create aggregate get_scores(scores) (
sfunc = save_scores,
finalfunc = calculate_scores,
stype = scores
);
还有一些检查:
select get_scores(row)
from (
values (4, 3.1), (3, 1.2), (2, 5.2), (1, 2)
) row
-- gives 1.2
select get_scores(row)
from (
values (4, 3.1), (3, 1.2), (2, 5.2), (1, 1)
) row
-- gives 3.1
由于使用了临时表,聚合只能在单个查询中使用一次。为简单起见,省略列 timestamp
。
【讨论】:
我的问题是我的函数需要处理多行的数据集。我按问题编辑以使其更清楚。 使用简单的功能是不可能的。您必须创建一个聚合。 哇!我确实读过它。你所写的关于聚合函数的内容是不正确的。这是唯一的解决方案,并不难。当然,如果我理解正确的话,你的目标是什么。 抱歉,您只是写了“创建聚合”,没有任何进一步的评论。这听起来好像你没有读过这个问题。 ;) 谢谢你的回答 - 有趣。我不明白临时表的性能影响。我可能每秒执行超过 100 个请求 - 我认为临时表仍会写入磁盘? 没关系。临时表在内存中处理(除非发生溢出)。但是,这种解决方案似乎并不是特别有效。以上是关于PostgreSQL:重用适用于虚拟表数据的函数代码的主要内容,如果未能解决你的问题,请参考以下文章