Como armazenar preços com datas efetivas?

21

Eu tenho uma lista de produtos. Cada um deles é oferecido por N fornecedores.

Cada fornecedor cita um preço para uma data específica. Esse preço é efetivo até que o provedor decida estabelecer um novo preço. Nesse caso, o provedor fornecerá o novo preço com uma nova data.

O cabeçalho da tabela MySQL atualmente se parece com:

provider_id, product_id, price, date_price_effective

A cada dois dias, compilamos uma lista de produtos / preços efetivos para o dia atual. Para cada produto, a lista contém uma lista classificada dos fornecedores que possuem esse produto específico. Dessa forma, podemos solicitar determinados produtos a quem quer que oferecer o melhor preço.

Para obter os preços efetivos, eu tenho uma instrução SQL que retorna todas as linhas que possuem date_price_effective >= NOW(). Esse conjunto de resultados é processado com um script ruby ​​que faz a classificação e a filtragem necessárias para obter um arquivo parecido com este:

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

Isso funciona bem para nossos propósitos, mas ainda sinto que uma tabela SQL provavelmente não é a melhor maneira de armazenar esse tipo de informação. Tenho a sensação de que esse tipo de problema foi resolvido anteriormente de outras maneiras mais criativas.

Existe uma maneira melhor de armazenar essas informações além do SQL? ou, se estiver usando SQL, existe uma abordagem melhor do que a que estou usando?

edmz
fonte
lal00: ​​Como mencionei em um de meus comentários, lida com encontros efetivos regularmente. Por favor, veja minha resposta para um método simples e eficaz de tratamento de datas. Ele não exige que se saiba o período em que um preço é efetivo quando uma nova linha de preços é criada, nem requer que você volte e modifique a linha anterior mais atual quando uma nova linha é criada.
23411 bit-twiddler

Respostas:

17

Para itens que variam com base no tempo (como poder responder a coisas como "qual era o preço de X na data D" ou "qual vaca estava no confinamento Q na data E"), recomendo a leitura do livro "Desenvolvendo o Tempo Aplicativos de banco de dados em SQL ". Enquanto este livro está esgotado, o autor graciosamente disponibilizou o PDF do livro e o CD associado em seu site.

http://www.cs.arizona.edu/~rts/publications.html (procure o primeiro item em "livros").

Para uma breve introdução online, consulte:

Tangurena
fonte
1
Bem, isso não era o que eu tinha em mente quando perguntei, é melhor! :)
edmz
3

Eu certamente armazenaria a data efetiva no banco de dados. Afinal, é provável que as pessoas desejem executar consultas para ver como o preço mudou ao longo do tempo ou fazer uma verificação cruzada de esquisitices em pedidos em relação à tabela histórica de preços do produto. Dependendo do tipo de consulta que você está executando e da frequência das alterações de preço, pode fazer sentido ter tabelas separadas para o preço atual e os preços históricos.

Na maioria dos sistemas que armazenam preços, você deseja uma coluna de data de vencimento, além da data efetiva, para facilitar a determinação de qual preço está atualmente em vigor, uma vez que evita o problema de ter que olhar para a linha anterior ou seguinte para descobrir qual preço estava em vigor em um determinado momento. Não sei ao certo o que sua NOW() >= date_price_effectivecondição está fazendo - presumivelmente, isso retorna o preço atual junto com todos os preços históricos anteriores que me parecem estranhos. Eu pensaria que o "preço efetivo" seria o preço atual que seria definido por algo comoNOW() BETWEEN date_price_effective AND date_price_expired

Também não tenho certeza de como seu arquivo deve ser. Não está claro para mim o que provider_1representa - o preço provider_id = 1? - ou como você está solicitando os dados do provedor - por que provider_1aparece primeiro product_id_1e terceiro no product_id_2.

Justin Cave
fonte
Justin, a data de validade faz sentido. Você estava certo, eu tinha o SQL ao contrário. O arquivo de saída não é muito relevante para minha pergunta, apenas adicionei como uma maneira de exemplificar que eu precisava classificar os produtos por preço.
Edmz
Não é necessário incluir uma data de validade em cada linha, pois isso apenas adiciona uma sobrecarga adicional, pois geralmente não é dado o período em que um preço é efetivo quando a linha é criada. Se tivermos N linhas para cada par producer_id / product_id em uma tabela, cada uma delas efetiva em uma determinada data, a linha com o maior valor date_price_effective menor ou igual a uma determinada data será o preço em vigor em Aquela data. Se você olhar para a minha postagem, verá o código SQL que executa esse tipo de consulta. Eu tenho que lidar com datas efetivas regularmente.
bit-twiddler
@ bit-twiddler - Certamente, não é necessário ter uma data de validade. No entanto, ter uma data de validade geralmente torna a consulta da tabela muito mais fácil e mais eficiente. Como as consultas de data efetivas geralmente são muito mais comuns que as alterações de preço, geralmente é uma troca que tenho o prazer de fazer.
23611 Justin Cave
3

Se eu entendi sua declaração do problema corretamente, você precisa de uma maneira de lidar com dados geracionais (ou seja, a tabela contém várias linhas para cada par provider_id / product_id, cada qual com sensibilidade à data). Nesse caso, você está procurando o preço mais recente de um produto com um valor date_price_effective menor ou igual a hoje. Esse tipo de situação é fácil de lidar usando uma subseleção 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() 
     );

Um preço é efetivo desde que tenha o maior valor date_price_effective menor ou igual à data em que a consulta é executada. Um valor date_price_effective maior que hoje é uma data efetiva futura. O código listado acima retorna os dados da linha para cada par provider_id / product_id que possui o valor date_price_effective mais próximo, mas não depois da data em que a consulta é executada. A solução agrupa automaticamente os preços em períodos efetivos. A chave primária para esta tabela seria o triplo {id_fornecedor, id_produto, data_effetivo_de_projeto};

bit-twiddler
fonte