SQL: Как получить предыдущую дату из таблицы без использования функции

#sql #postgresql #window-functions #sql-view

#sql #postgresql #окно-функции #sql-просмотр

Вопрос:

У меня есть таблица под названием Stocks, которая содержит дату, StocksID и цену. Таблица содержит данные о цене нескольких различных рыночных акций в 2018 году. Я хотел бы создать представление таблицы Stocks, в которой отображаются дата, StocksID, previous_price, цена и change_in_price. Previous_price означает цену той же акции за день до этого. У меня возникла проблема с получением previous_price без использования какой-либо встроенной функции.

Я попытался получить previous_price, получив цену с предыдущей даты, но я не знаю, как получить предыдущую дату.

Любая помощь приветствуется, спасибо!

Пример вывода:

 Date       | StocksID  | prevprice | price | change 
----------- ----------- ----------- ------- --------
2012-01-04 |     1     |      0.91 |  0.92 |   0.01
2012-01-05 |     1     |      0.92 |  0.91 |  -0.01 
2012-01-06 |     1     |      0.91 |  0.90 |  -0.01 
2012-01-09 |     1     |      0.90 |  0.89 |  -0.01
  

Ответ №1:

Это выглядит как хороший вариант использования для оконной функции LAG() Postgres, доступной с версии 9.4:

 SELECT 
    s.*, 
    LAG(price) OVER(PARTITION BY s.stocksID ORDER BY s.date) previous_price,
    price - LAG(price) OVER(ORDER BY s.date) change
FROM Stocks s
  

Это даст вам разницу с предыдущей ценой того же самого, stocksID заказанного date . Пожалуйста, обратите внимание, что, в зависимости от ваших данных, это может быть не цена предыдущего дня (если, например, у вас есть задержки в ряду дат).

Комментарии:

1. Я принял «Без функций» за это тоже, но если OP означает только пользовательские функции, тогда вы правы.

2. @TomC: да… Я не могу представить, почему OP не захотел бы использовать встроенные функции Postgres.

Ответ №2:

Вы можете сделать это с помощью self join и not exists.

p1 является текущим, p2 является предыдущим

 select p1.*, p2.* 
from price p1
left join price p2 on p2.StocksID=p1.StocksID and p2.Date<p1.Date
    and not exists(
        select * from price p3 
        where p3.StocksID=p1.StocksID and p3.Date<p1.Date
        and p3.Date>p2.date
    )