选择时间间隔内的第一行和最后一行

时间:2015-01-14 23:12:21

标签: sql postgresql aggregate-functions greatest-n-per-group window-functions

我有一个名为trades的表,用于使用以下架构持有货币交易数据:

id        - uuid
timestamp - timestamp without time zone
price     - numeric

我希望能够以一种可以构建蜡烛图的方式进行查询。为此,我需要第一个价格最后价格最高价格最低价格,按分组时间间隔。到目前为止,我有这个:

CREATE FUNCTION ts_round( timestamptz, INT4 ) RETURNS TIMESTAMPTZ AS $$
SELECT 'epoch'::timestamptz
     + '1 second'::INTERVAL * ( $2 * ( extract( epoch FROM $1 )::INT4 / $2 ) );
$$ LANGUAGE SQL;

SELECT ts_round( timestamp, 300 ) AS interval_timestamp
     , max(price) AS max, min(price) AS min
FROM trades
GROUP BY interval_timestamp
ORDER BY interval_timestamp DESC

如何在这些时间间隔内获得第一个价格最后价格

2 个答案:

答案 0 :(得分:4)

我认为这是您想要的查询:

SELECT ts_round( timestamp, 300 ) AS interval_timestamp,
       max(firstprice) as firstprice,
       max(lastprice) as lastprice,
       max(price) AS maxprice, min(price) AS minprice
FROM (SELECT t.*,
             first_value(price) over (partition by ts_round(timestamp, 300) order by timestamp) as firstprice,
             first_value(price) over (partition by ts_round(timestamp, 300) order by timestamp desc) as lastprice
      FROM trades t
     ) t
GROUP BY interval_timestamp
ORDER BY interval_timestamp DESC;

答案 1 :(得分:2)

这对所有窗口函数使用单个窗口,没有子查询。应该比目前接受的答案更快。

SELECT DISTINCT ON (1)
       ts_round(timestamp, 300) AS interval_timestamp
     , min(price)         OVER w AS min_price
     , max(price)         OVER w AS max_price
     , first_value(price) OVER w AS first_price
     , last_value(price)  OVER w AS last_price
FROM   trades
WINDOW w AS (PARTITION BY ts_round(timestamp, 300) ORDER BY timestamp
             ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
ORDER  BY 1 DESC;

定义"首先"和"最后"根据{{​​1}},此列需要是唯一的,或者查询是不明确的,并且您可以从相同的同行中获取任意选择。

与自定义窗口框架的解释相似的答案:

按顺序编号引用的说明:

除此之外:不要使用"时间戳"作为标识符。它是一个基本类型名称,容易出错。