Условный заказ по запросу с текущей датой - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть товары в таблице базы данных 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' в примере выше).

Спасибо за вашу помощь.

Обновление:

Из комментариев ниже я понимаю, возможно ли как-то сделать что-то вроде этого:

  1. Будет индекс на standard_price, promo_price , promo_date_from и promo_date_to.

  2. Использование индексов над этими запросами будет быстрым:

    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

  3. Приведенные выше запросы дают мне два отсортированных набора с пустым пересечением, поэтому использование UNION ALL безопасно. Теперь лучшая оптимизация будет заключаться в объединении их с использованием некоторого алгоритма сортировки слиянием.

Итак, вопрос в том, есть ли в Postgresql что-то, что может объединить эти два отсортированных наборы в один набор (по current_price столбцу)? И, наконец, после этого применить лимит / смещение для нумерации страниц?

1 Ответ

0 голосов
/ 25 февраля 2020
CREATE OR REPLACE FUNCTION prices (d DATE DEFAULT now())
RETURNS TABLE (id int, name VARCHAR, price decimal(12,2)) AS $$
SELECT
  id,
  name,
  CASE WHEN $1 BETWEEN promo_date_from AND promo_date_to
    THEN promo_price
    ELSE standard_price
  END
  FROM your_table
$$ LANGUAGE SQL;

Дата по умолчанию равна текущей дате, или вы можете указать дату значения в качестве параметра:

select * from prices() order by price;
select * from prices('2020-02-02') order by price;
...