2

У меня есть таблица с именем 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 

Как получить первой цены и цена последней в пределах этих интервалов?

+0

Как вы определяете «первую цену» и «последнюю цену»? По метке времени? –

+0

Я серьезно сомневаюсь, что ваша функция делает то, что вы на самом деле хотите. Это эффективно * усечение * до * n * -секундных интервалов, после * округления * до полных секунд. Я подозреваю, что вы действительно хотите либо усечь ***, либо *** округлить до * n * -секундных интервалов. Правильно? –

+1

Возможный дубликат [заданное время/интервал для вычисления значения open/high/low/close в каждой сгруппированной информации] (http://stackoverflow.com/questions/27399054/given-time-interval-to-calculate-open-high -low-close-value-in-each-grouped-data) – radar

ответ

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; 
+0

Можно иметь функцию окна по результату функции агрегата на одном уровне запросов, но не наоборот.В то время как 'min()' и 'max()' могут использоваться для любой цели, 'first_value()' и 'last_value()' являются выделенными функциями окна. Это синтаксическая ** бессмыслица **, вам нужен подзапрос, чтобы он работал. Тем не менее, похоже, что люди не голосовали за него. –

+0

** Неправильно ** после исправления. Определение фрейма по умолчанию для оконных фреймов - «ROWS BETWEEN UNOCUNDED PRECEDING AND CURRENT ROW». В вашем подзапросе вы фактически получаете цену строки * current * как 'lastprice'. После 'max (lastprice)' во внешнем запросе вы фактически возвращаете 'max (price)' второй раз, что бессмысленно. Все еще не заставляет людей голосовать за него. –

+0

Теперь это должно сработать. –

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; 

Для определения «первый» и «последний» в timestamp, этот столбец должен быть уникальным или запрос неоднозначен и йо получить произвольный выбор из равных аналогов.

Подобный ответ с объяснением для пользовательских оконной рамы:

Объяснение для справки по порядковым номерам:

Кроме того: не используйте «timestamp» в качестве идентификатора. Это основное имя типа, которое подвержено ошибкам.

Смежные вопросы