Как хранить цены, которые имеют даты вступления в силу?

21

У меня есть список продуктов. Каждый из них предлагается N провайдерами.

Каждый провайдер указывает нам цену на конкретную дату. Эта цена действует до тех пор, пока поставщик не решит установить новую цену. В этом случае поставщик предоставит новую цену с новой датой.

Заголовок таблицы MySQL в настоящее время выглядит так:

provider_id, product_id, price, date_price_effective

Через день мы составляем список продуктов / цен, действующих на текущий день. Для каждого продукта список содержит отсортированный список поставщиков, которые имеют этот конкретный продукт. Таким образом, мы можем заказать определенные продукты у тех, кто предлагает лучшую цену.

Чтобы получить эффективные цены, у меня есть оператор SQL, который возвращает все строки, которые есть date_price_effective >= NOW(). Этот набор результатов обрабатывается с помощью сценария ruby, который выполняет сортировку и фильтрацию, необходимые для получения файла, который выглядит следующим образом:

product_id_1,provider_1,provider_3,provider8,provider_10...
product_id_2,provider_3,provider_2,provider1,provider_10...

Это прекрасно работает для наших целей, но у меня все еще есть зуд, что таблица SQL, вероятно, не лучший способ для хранения такого рода информации. У меня такое чувство, что проблема такого рода была решена ранее другими, более творческими способами.

Есть ли лучший способ хранить эту информацию, кроме как в SQL? или, если используется SQL, есть ли лучший подход, чем тот, который я использую?

edmz
источник
lal00: ​​Как я уже упоминал в одном из моих комментариев, я регулярно занимаюсь эффективными знакомствами. Пожалуйста, смотрите мой ответ для простого эффективного метода обработки даты. Не требуется знать период действия цены при создании новой строки цены, а также не требуется возвращать изменение предыдущей самой последней строки при создании новой строки.
немного крутой

Ответы:

17

Для предметов, которые меняются в зависимости от времени (например, возможность ответить на такие вещи, как «какая была цена Х на дату D» или «какая корова была на откормочной площадке Q на дату E»), я рекомендую прочитать книгу «Разработка ориентирована на время» Приложения баз данных в SQL. " В то время как эта книга не печатается, автор любезно предоставил PDF-версию книги и соответствующий компакт-диск на своем веб-сайте.

http://www.cs.arizona.edu/~rts/publications.html (ищите первый пункт в разделе «книги»).

Для краткого введения онлайн, см .:

Tangurena
источник
1
Ну, это не то, что я имел в виду, когда я спросил, это лучше! :)
edmz
3

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

В большинстве систем, в которых хранятся цены, вам потребуется столбец с датой истечения срока действия в дополнение к дате вступления в силу, чтобы было легче определить, какая цена действует в данный момент, поскольку это избавляет вас от необходимости просматривать предыдущую или следующую строку на рисунке. выяснить, какая цена действовала в данный момент времени. Мне не ясно, что делает ваше NOW() >= date_price_effectiveсостояние - возможно, это возвращает текущую цену вместе со всеми предыдущими историческими ценами, что мне кажется странным. Я думаю, что «эффективной ценой» будет текущая цена, которая будет определяться чем-то вродеNOW() BETWEEN date_price_effective AND date_price_expired

Я также не уверен, как должен выглядеть ваш файл. Мне непонятно, что provider_1представляет собой - provider_id = 1 цена? - или как вы заказываете данные поставщика - почему они provider_1появляются сначала для, product_id_1а третьи для product_id_2.

Джастин Кейв
источник
Джастин, срок годности имеет смысл. Вы были правы, у меня был SQL наоборот. Выходной файл не очень уместен для моего вопроса, я просто добавил, чтобы показать, что мне нужно отсортировать товары по цене.
edmz
Не нужно указывать дату истечения срока действия в каждой строке, так как это только добавляет дополнительные накладные расходы, поскольку обычно не дается период действия цены при создании строки. Если у нас есть N строк для каждой пары производителей_идентификатора_продукта в таблице, каждая из которых действует на определенную дату, строка с наибольшим значением date_price_effective, меньшим или равным указанной дате, является ценой, действующей на эта дата Если вы посмотрите на мою публикацию, вы увидите код SQL, который выполняет этот тип запроса. Я должен иметь дело с датами вступления в силу на регулярной основе.
немного крутой
@ bit-twiddler - Конечно, не обязательно иметь срок годности. Однако срок годности обычно делает запрос к таблице намного проще и эффективнее. Так как запросы на эффективные даты, как правило, встречаются гораздо чаще, чем изменения цен, это, как правило, компромисс.
Джастин Кейв
3

Если я правильно понимаю формулировку вашей проблемы, вам нужен способ обработки данных поколения (т. Е. Таблица содержит несколько строк для каждой пары provider_id / product_id, каждая из которых является чувствительной к дате). В этом случае вы ищете самую последнюю цену для продукта со значением date_price_effective, которое меньше или равно сегодняшнему. Ситуация такого типа легко обрабатывается с помощью подвыбора SQL.

 SELECT 
   provider_id, product_id, price, date_price_effective 
 FROM 
   price_table a 
 WHERE 
   date_price_effective = 
     (
       SELECT 
         MAX(date_price_effective) 
       FROM 
         price_table b 
       WHERE 
         b.provider_id = a.provider_id AND 
         b.product_id = a.product_id AND
         b.date_price_effective <= NOW() 
     );

Цена действует до тех пор, пока она имеет наибольшее значение date_price_effective, которое меньше или равно дате выполнения запроса. Значение date_price_effective, большее, чем сегодня, является будущей датой вступления в силу. Приведенный выше код возвращает данные строки для каждой пары provider_id / product_id, значение которой date_price_effective ближе всего, но не позднее даты выполнения запроса. Решение автоматически объединяет цены в эффективные диапазоны дат. Первичным ключом для этой таблицы будет тройной {provider_id, product_id, date_price_effective};

бит-бездельник
источник