我有fucntion pb(IDCODE,0)
运行IDCODE=320
,并提供此示例数据:
select *
from pb(320,0)
logid entrydate qty
1 1.10.17 5
2 1.10.17 6
3 1.10.17 5
4 1.10.17 -3
5 2.10.17 6
6 3.10.17 -100
*它实际上提供了更多行(如20000),但我将其缩小为示例
pb是一个非常繁重的功能,但简单来说,它根据订单显示活动。
我想在entrydate
的最后一行之后找到qty<0
首次出现的qty>0
。
为了做到这一点,我需要做这样的事情:
Select Min(logid) where qty<0 and logid>(select max(logid) where qty>=0)
在上面的示例中,请求的结果为3.10.17
这是因为:
logid=5
是max(logid) where qty>=0
和
logid=6
是Min(logid) where qty<0 and logid>(select max(logid) where qty>=0)
实际上是:Select Min(logid) where qty<0 and logid>5
所以我写了以下查询:
select entrydate
from pb(320,0)
where logid= ( SELECT min(logid)
FROM pb(320,0)
where qty<0 and logid>(SELECT coalesce(max(logid),0)
FROM pb(320,0)
WHERE qty >= 0))
效果很好但是我称之为函数pb(320,0)
是我的3倍。
这是非常耗时的,不用说我实际上在许多IDCODES(如214)上运行此查询,因此pb(IDCODE,0)
实际运行214*3
这太可怕了。
我该怎么办?
答案 0 :(得分:2)
首先,使用CTE,因为Postgres可能会实现CTE。
但是,如果使用窗口函数,则只需要一个表引用:
with t as (
select *
from pb(320,0)
)
select t.*
from (select t.*, max(case when qty > 0 then logid end) over () as last_poslogid
from t
) t
where id > last_poslogid and qty < 0
order by id
fetch first 1 row only;
更新版本的Postgres支持filter
子句,它比case
更有效。