在子查询的FROM中使用Postgres窗口语句
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在子查询的FROM中使用Postgres窗口语句相关的知识,希望对你有一定的参考价值。
我有以下SUB QUERY作为SELECT语句的一部分。这应该花费一个计算时间,远离另一个计算时间。
但Postgres不喜欢在FROM子句中使用Window函数。
(SELECT count(*) AS work_hours
FROM generate_series (TIMESTAMP 'epoch' + MAX(wog.endtime) OVER(PARTITION BY woas.workorderid ORDER BY wog.endtime DESC)/1000 * INTERVAL '1 second'
, TIMESTAMP 'epoch' + nth_value(wog.endtime,2) OVER(PARTITION BY woas.workorderid ORDER BY wog.endtime DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)/1000 * INTERVAL '1 second' - interval '1h'
, interval '1h') h
WHERE EXTRACT(ISODOW FROM h) < 6
AND h::time >= '08:00'
AND h::time <= '18:00') AS "Max minus Second Max",
Postgres返回以下错误:
ERROR: cannot use window function in function expression in FROM
如何重新格式化上述语句,以便它可以无误地解析?
更新:
我不认为查询的结构是问题。如果我用时间戳字符串代替函数它可以正常工作。
(SELECT count(*) AS work_hours
FROM generate_series (timestamp '2018-01-06 13:30'
, timestamp '2018-01-08 21:29' - interval '1h'
, interval '1h') h
WHERE EXTRACT(ISODOW FROM h) < 6
AND h::time >= '08:00'
AND h::time <= '18:00') "Time Difference" from workorder wo
答案
在“FROM”子句之后,需要一个表/视图来查询数据。
您重构查询,如下所示:
select count(*) from (
select generate_series( ....)
where (cond1 and cond2..)
当你将函数放在“from”子句中时,它显然不起作用。
另一答案
如果您还没有解决方案,可能需要尝试此操作。我认为它做你想要的。
设置测试:我希望与你的情况相似。
create table work_order_times
(
work_order_id integer,
end_time bigint -- milliseconds
);
insert into work_order_times (work_order_id, end_time) values (23, extract(epoch from now()) * 1000);
insert into work_order_times (work_order_id, end_time) values (23, (extract(epoch from now()) - 20000) * 1000);
insert into work_order_times (work_order_id, end_time) values (57, (extract(epoch from now()) - 40000) * 1000);
insert into work_order_times (work_order_id, end_time) values (57, (extract(epoch from now()) - 60000) * 1000);
insert into work_order_times (work_order_id, end_time) values (57, (extract(epoch from now()) - 80000) * 1000);
检查设置:
select
work_order_id,
end_time,
to_timestamp(end_time / 1000) as end_timestamp
from
work_order_times
order by
work_order_id,
end_time;
work_order_id | end_time | end_timestamp
---------------+---------------+------------------------
23 | 1516251234772 | 2018-01-18 04:53:54+00
23 | 1516271234769 | 2018-01-18 10:27:14+00
57 | 1516191234774 | 2018-01-17 12:13:54+00
57 | 1516211234773 | 2018-01-17 17:47:14+00
57 | 1516231234772 | 2018-01-17 23:20:34+00
(5 rows)
查询:
select
work_order_id,
generate_series (penultimate_timestamp, latest_timestamp, interval '1 hour')
from
(
select
work_order_id,
to_timestamp(latest_end_time / 1000) as latest_timestamp,
to_timestamp(penultimate_end_time / 1000) as penultimate_timestamp
from
(
select
work_order_id,
row_number() over last_2_timestamps as row_number,
max(end_time) over last_2_timestamps as latest_end_time,
lead(end_time) over last_2_timestamps as penultimate_end_time
from
work_order_times
window
last_2_timestamps as (partition by work_order_id order by end_time desc)
) x
where
row_number = 1
) y;
结果:
work_order_id | generate_series
---------------+------------------------
23 | 2018-01-18 04:53:54+00
23 | 2018-01-18 05:53:54+00
23 | 2018-01-18 06:53:54+00
23 | 2018-01-18 07:53:54+00
23 | 2018-01-18 08:53:54+00
23 | 2018-01-18 09:53:54+00
57 | 2018-01-17 17:47:14+00
57 | 2018-01-17 18:47:14+00
57 | 2018-01-17 19:47:14+00
57 | 2018-01-17 20:47:14+00
57 | 2018-01-17 21:47:14+00
57 | 2018-01-17 22:47:14+00
(12 rows)
PostgreSQL文档确实提到了关于如何嵌套窗口函数的一些限制,但它看起来像这样工作。
将endtime存储为时间戳而不是毫秒数会使事情稍微简单一些,这可能就像它看起来那样,但也许你没有机会这样做。
以上是关于在子查询的FROM中使用Postgres窗口语句的主要内容,如果未能解决你的问题,请参考以下文章