繁体   English   中英

在子查询的FROM中使用Postgres window语句

[英]Using a Postgres window statement in the FROM of a sub query

我将以下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文档确实提到了有关如何嵌套窗口函数的一些限制,但似乎可以这样工作。

将结束时间存储为时间戳(而不是毫秒)将使事情变得简单一些,这看起来似乎是这样,但是也许您没有机会这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM