I am trying to query a table in PostgreSQL 8.4.2 server for to get open-high-low-close data. The table and my first query are below.
Question: Is there a way to get the same results without using subqueries as in the example query below? Perhaps using FIRST_VALUE() or LAST_VALUE() window methods?
-- 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)
);
I would like to get sub-day resolution. This appears to work well.
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;
Thank you, Scott. You answer helped me get to the following solution.