У меня есть товары в таблице базы данных Postgresql со следующими столбцами:
standard_price -- Price of product
promo_price -- Price of product in sale
promo_date_from -- Sale is valid from
promo_date_to -- Sale is valid to
Задача состоит в том, чтобы упорядочить товары по их текущей цене. Текущая цена - promo_price, когда сегодня - в рамках promo_date_from и promo_date_to; в противном случае текущая цена - standard_price.
Одним из возможных решений является что-то вроде этого:
SELECT * FROM products
ORDER BY
CASE WHEN promo_date_from <= '2020-02-24'::date AND '2020-02-24'::date <= promo_date_to THEN
promo_price
ELSE
standard_price
END;
Однако это решение довольно медленное, и я не знаю, как его ускорить? Есть ли какой-либо индекс, который может быть полезен в этом сценарии или лучше подходит, например, представления, функции, ...?
Основная проблема, я думаю, в том, что запрос не "stati c" - это зависит от параметра даты, который является частью запроса ('2020-02-24' в примере выше).
Спасибо за вашу помощь.
Обновление:
Из комментариев ниже я понимаю, возможно ли как-то сделать что-то вроде этого:
Будет индекс на standard_price
, promo_price
, promo_date_from
и promo_date_to
.
Использование индексов над этими запросами будет быстрым:
query_promo = SELECT *, promo_price AS current_price FROM products WHERE '2020-02-24'::date BETWEEN promo_date_from AND promo_date_to ORDER BY promo_price
и
query_standard = SELECT *, standard_price AS current_price FROM products WHERE NOT('2020-02-24'::date BETWEEN promo_date_from AND promo_date_to) ORDER BY standard_price
Приведенные выше запросы дают мне два отсортированных набора с пустым пересечением, поэтому использование UNION ALL безопасно. Теперь лучшая оптимизация будет заключаться в объединении их с использованием некоторого алгоритма сортировки слиянием.
Итак, вопрос в том, есть ли в Postgresql что-то, что может объединить эти два отсортированных наборы в один набор (по current_price
столбцу)? И, наконец, после этого применить лимит / смещение для нумерации страниц?