PostgreSQL: ДИАПАЗОН МЕЖДУ ИНТЕРВАЛОМ «10 ДНЕЙ» И ТЕКУЩЕЙ СТРОКОЙ - PullRequest
1 голос
/ 14 марта 2019

У меня есть таблица, в которой хранится ежедневная цена каждого товара. Если цена не была обновлена, для этого товара в этот день нет записи.

Мне нужно написать запрос, который извлекает для каждого элемента самую последнюю цену с окном просмотра в 10 дней от текущей даты строки, в противном случае возвращается NULL. Я думал достичь этого с помощью оператора RANGE BETWEEN INTERVAL. Что-то вроде:

SELECT
    DATE(datetime),
    item_id,
    LAST(price) OVER(
        PARTITION BY item_id
        ORDER BY datetime DESC
        RANGE BETWEEN INTERVAL '10 DAYS' AND CURRENT ROW
    ) AS most_recent_price_within_last_10days
FROM ...
GROUP BY
    date,
    item_id,
    price

К сожалению, этот запрос вызывает ошибку:

LINE 20:  RANGE BETWEEN INTERVAL '10 DAY' PRECEDING AND CURRENT ROW
          ^

Я наткнулся на старое сообщение в блоге, в котором говорится, что в Postgres такая операция невозможна. Это все еще точно?

Ответы [ 2 ]

1 голос
/ 14 марта 2019

Один метод заключается в использовании LAG() и некотором сравнении:

(CASE WHEN LAG(datetime) OVER (PARTITION BY item_id ORDER BY datetime) > datetime - interval '10 days'
      THEN LAG(price) OVER (PARTITION BY item_id ORDER BY datetime)
 END) as most_recent_price_within_last_10days

То есть искомая цена находится в предыдущей строке.Вопрос только в том, является ли дата в этой строке достаточно недавней.

1 голос
/ 14 марта 2019

Вы можете использовать ROW_NUMBER () для получения самой последней записи за последние 10 дней для каждого элемента:

SELECT * 
FROM (
    SELECT
        DATE(datetime),
        item_id,
        price AS most_recent_price_within_last_10days,
        ROW_NUMBER() OVER(PARTITION BY item_id ORDER BY datetime DESC) rn
    FROM ...
    WHERE datetime > NOW() - INTERVAL '10 DAY'
) x WHERE rn = 1

В подзапросе предложение WHERE выполняет фильтрацию по диапазону дат; ROW_NUMBER () присваивает ранг каждой записи в группах записей, имеющих одинаковый item_id, с самой последней записью первой. Затем внешний запрос просто фильтрует записи, имеющие номер строки 1.

...