2016-07-27 81 views
5

比方說,我有如下表:PostgreSQL - 如何創建具有條件的窗口框架?

CREATE TABLE stock_prices (
    stock TEXT NOT NULL, 
    date DATE NOT NULL, 
    price REAL NOT NULL, 
    UNIQUE (stock, date) 
); 

我想計算每一天,每一個股票的最高價格在之前3個月的窗口。

我不能做一個簡單的自我加入date - INTERVAL(3 'MONTH')因爲我的stock_price表有一些節假日和週末的「漏洞」。同樣一個天真的窗口也不起作用:

SELECT 
    stock, 
    date, 
    LAST_VALUE(price) OVER (PARTITION BY stock ORDER BY date ROWS 90 PRECEDING) 
FROM stock_prices 

我幾乎想要一個窗口框架與基於當前行的條件。 PostgreSQL有可能嗎?

+0

一個解決方案是使用'generate_series()'生成額外的行。 –

+0

非問題:如果日期範圍內有*孔*,那麼*孔*不能包含最高價格。 – joop

+0

已經在dba.se上討論過:[使用窗口函數的日期範圍滾動和](http://dba.stackexchange.com/q/114403/57105)。 dba.se中的問題使用SQL Server,但最新的Postgres和最新的SQL Server具有與Window函數相關的一組相同功能,因此可以將最小的更改應用於Postgres。它們都不支持'RANGE'窗口框架,這在這個問題中很重要。可以使用子查詢,也可以用@klin顯示的日期填充日期。 –

回答

5

您可以使用函數generate_series()填充缺失行的表,因此窗口函數將返回正確的數據。您可以在generate_series()選擇指定報告開始和結束日期的期限:

select 
    stock, 
    date, 
    price, 
    max(price) over (partition by stock order by date rows 90 preceding) 
from (
    select d::date as date, s.stock, sp.price 
    from generate_series('2016-01-01'::date, '2016-07-28', '1d') g(d) 
    cross join (
     select distinct stock 
     from stock_prices 
    ) s 
    left join stock_prices sp on g.d = sp.date and s.stock = sp.stock 
) s 
order by 1, 2; 

用一個簡單的子查詢這一替代方案:

select 
    stock, 
    date, 
    price, 
    (
     select max(price) 
     from stock_prices sp2 
     where sp2.stock = sp1.stock 
     and sp2.date >= sp1.date- interval '90days' 
     and sp2.date <= sp1.date 
    ) highest_price 
from 
    stock_prices sp1 
order by 1, 2; 

將更加昂貴。在這種情況下,你應該強制使用索引

create index on stock_prices (stock, date); 
0

的generate_series選項應該很好地工作,雖然自個月並不總是三十日內予以不會總是對準日曆月。

如果您想使用間隔,您也可以進行自我加入和聚合。這將加入各行到滿足條件的(在這種情況下,我已經設置在第1周的時間間隔)的所有行,並且該結果集中獲取最大價值:

select a.stock, 
     a.date, 
     a.price, 
     max(b.price) 
from stock_prices as a 
     left join 
     stock_prices as b 
     on a.stock = b.stock 
     and b.date between (a.date - interval '7 days') and a.date 
group by a.stock, 
     a.date, 
     a.price 
order by a.stock, 
     a.date 

SQL小提琴這裏:http://sqlfiddle.com/#!15/bbec8/2