我有以下类型的几个大查询(为简洁起见,已简化)。
create function myfunction()
returns void
as $$
begin
...
with t as (
total as total,
total * 100 / total as total_percent,
total / people.count as total_per_person,
part1 as part1,
part1 * 100 / total as part1_percent,
part1 / people.count as part1_per_person,
part2 as part2,
part2 * 100 / total as part2_percent,
part2 / people.count as part2_per_person,
...
from (
select
total.amount as total
part1.amount as part1
part2.amount as part2
...
people.amount as people
from (select ...from mytable..) total
left join (select ...from mytable..) part1 on ...
left join (select ...from mytable..) part2 on ...
...
left join (select ...from mytable..) people on ...
) r
)
insert into another_table -- << NOW I NEED TO REPLACE THIS WITH "RETURN QUERY"
select .., total from t
union select .., total_percent from t
union select .., total_per_person from t
union select .., part1 from t
union select .., part1_percent from t
union select .., part1_per_person from t
union select .., part2 from t
union select .., part2_percent from t
union select .., part2_per_person from t
...
...
$$ language plpgsql;
它之所以如此之大,是因为大多数列来自其他列。查询旨在最大限度地减少数据和聚合中的重复,从而最大限度地缩短运行时间(因为此查询运行需要大约10秒,因为mytable
只有不超过400万行)。所有15个列都插入到另一个表中,并与union运算符结合使用。
with .. as ..
条款对此方案起到了很好的作用。但是现在,重构程序,我必须将生成的数据集交给另一个函数进行后期处理(而不是插入到another_table中)。
所以,我必须将insert into another_table
替换为return query
,但WITH .. AS ..
不喜欢这样。
换句话说,这是我想要达到的更新功能(这不起作用 - 解释器在return query
阻止后不期望with .. as
:
create function myfunction()
returns setof data -- << now returning a data set
as $$
begin
...
with t as (
--SAME QUERY
) r
)
return query -- << line that is changed
-- SAME SELECT HERE
...
$$ language plpgsql;
现在我的问题是,WITH .. AS ..
有哪些替代方案?所以,我可以使用return query
。我打算尝试使用临时表,但我仍然很好奇如何重写用with .. as ...
编写的查询。
答案 0 :(得分:2)
问题中的查询有几个明显无意义的部分。既然您之前一直在执行它,我认为这些都是手工简化的工件?
比如: 会毫无意义,因为它会烧毁到total * 100 / total
100
。
或者:没有连接条件的连接,这是普通的语法错误。
除此之外, RETURN QUERY
不是SQL而是plpgsql命令:
要么你忽略了提到你正在使用带有plpgsql代码的function
或DO
语句,要么你试图使用无效的SQL语法。
在 plpgsql 中,如果您在 SQL查询之前放置RETURN QUERY
,CTE (Common Table Expression) - 那&# 39;是WITH
子句的规范名称 - 是SQL语句的一部分:
RETURN QUERY -- plpgsql command
WITH t AS ( ... ) -- here starts the SQL query
SELECT .., total FROM t
UNION SELECT .., total_percent FROM t
UNION SELECT.., total_per_person FROM t
-- etc.
在此期间,最后一部分很可能 错误 。我很确定你想要UNION ALL
,而不是UNION
,它会在结果中折叠任何重复项。
更好的是,使用这种智能技术,在VALUES
加入LATERAL
表达式中使用...
SELECT t1.*
FROM t, LATERAL (
VALUES
(.., t.total) -- whatever you may be hiding behind ".."
, (.., t.total_percent)
, (.., t.total_per_person)
, (.., t.part1)
, (.., t.part1_percent)
-- etc.
) t1 ("name_for ..", total);
表达式来反对&#34;反向转动&#34;你的长行:
f = lambda x: x.prod() - 1 # cumulative product of all returns ("gret": 1+ret) in each week for each firm
weekly_rets = df.groupby('PERMNO').resample('W-WED', closed='left', how=f)
应该大大缩短和便宜。在dba.SE
的相关答案中向@Andriy提出这个想法