4

我正在尝试查询 PostgreSQL 8.4.2 服务器中的表以获取打开-高-低-关闭数据。该表和我的第一个查询如下。

问题: 有没有一种方法可以在不使用子查询的情况下获得相同的结果,如下面的示例查询?也许使用 FIRST_VALUE() 或 LAST_VALUE() 窗口方法?

-- FIRST ATTEMPT AT OHLC
SELECT
  contract_id
, TO_CHAR(ts, 'YYMMDDHH24MI')
, (SELECT price FROM fill minF WHERE minF.fill_id = MIN(f.fill_id)) AS open
, MAX(f.price) AS high
, MIN(f.price) AS low
, (SELECT price FROM fill maxF WHERE maxF.fill_id = MAX(f.fill_id)) AS close
FROM fill f
GROUP BY 1,2
ORDER BY 1,2;

-- SIMPLIFIED DDL
CREATE TABLE fill
(
    contract_id SEQUENCE PRIMARY KEY
,   ts          TIMESTAMP
,   price       NUMERIC(10,4)
);
4

4 回答 4

3

你有你的分组到分钟。我将假设这是错误的,因为这些通常是在白天完成的。如果我错了,你必须改回来。

SELECT DISTINCT contract_id, ts::date,
  min(price) OVER w,
  max(price) OVER w,
 first_value(price) OVER w, 
 last_value(price) OVER w
FROM fill
WINDOW w AS (PARTITION BY contract_id, ts::date ORDER BY ts)
ORDER BY 1,2
于 2010-03-29T23:53:56.750 回答
3

我想获得亚日解决方案。这似乎运作良好。

SELECT
  contract_id
, the_minute
, open
, high
, low
, close
FROM 
(
  SELECT
    contract_id
  , TO_CHAR(ts, 'YYMMDDHH24MI') AS the_minute
  , MIN(price) OVER w            AS low
  , MAX(price) OVER w            AS high
  , LAST_VALUE(price) OVER w     AS open   -- Note the window is in reverse (first value comes last)
  , FIRST_VALUE(price) OVER w    AS close  -- Note the window is in reverse (last value comes first)
  , RANK() OVER w                AS the_rank
  FROM fill
  WINDOW w AS (PARTITION BY contract_id, TO_CHAR(ts, 'YYMMDDHH24MI') ORDER BY fill_id DESC)
) AS inr
WHERE the_rank = 1
ORDER BY 1, 2;

谢谢你,斯科特。您的回答帮助我找到了以下解决方案。

于 2010-03-30T13:03:17.867 回答
3

我找到了一个非常方便的方法,它使用 PostgresSQL 的Timescale 扩展。它提供了按任意时间间隔分组的能力。该函数被调用time_bucket()并具有与内置date_trunc()函数相同的语法,但将间隔而不是时间精度作为第一个参数。无需使用窗口/分区。在这里你可以找到它的 API Docs。这是一个例子:

SELECT  
    time_bucket('1 minute', timestamp_) timebucket,
    (array_agg(price ORDER BY timestamp_ ASC))[1] open,
    MAX(price) high,
    MIN(price) low,
    (array_agg(price ORDER BY timestamp_ DESC))[1] close,
    SUM(turnover) turnover,
    COUNT(*) nr_ticks
FROM price_tick
GROUP BY timebucket
ORDER BY timebucket

如果您希望使用新摄取的数据自动更新“按间隔分组”视图,并且如果您想经常查询这些视图,您也可以查看连续聚合视图。这可以为您节省大量资源,并使您的查询速度更快。

于 2020-04-16T19:58:38.140 回答
0

这就是我解决它的方法:

select FLOOR(MIN(ts) / :period) * :period                    as timestamp,
       SUBSTRING_INDEX(MIN(CONCAT(ts, '_', price)), '_', -1) as open,
       max(price)                                            as high,
       min(price)                                            as low,
       SUBSTRING_INDEX(MAX(CONCAT(ts, '_', price)), '_', -1) as close,
       sum(amount)                                           as volume
from uni_tx
where asset = :asset
  and ts between :startTime and :endTime
GROUP BY FLOOR(ts / :period)
order by timestamp
于 2021-03-01T16:26:30.940 回答