I am currently creating a website which will allow people to buy consumer products (deodorant, shampoo, toothpastes, etc…) from a store. Those products tend to change price and other details twice per year or more. And I want to show past purchases’ prices and other details to the client. And I wanted to know what the best approach is. I’ve come up with the following approaches. Are they any good?


1st. Approach: I have a Product table, with the columns that tend to change, appended with the time of change as a suffix.

1st Approach.
2nd Approach: In this one, I have the price and other details in a separate column. 2nd. Approach

I did make some research: How to store prices that have effective dates? http://talentedmonkeys.wordpress.com/2010/05/15/temporal-data-in-a-relational-database/

But couldn't find them appropriate for my problem.


5 Answers 5


Instead of creating a separate table for each date, create a single details table and index by product id and effective date:


This way, you just insert a new row each time the details change.

insert into ProductDetails( productId, dateEffective, price )
values ( 1234567, '10/06/2014', 1.25 );

So you get the price based on the product id and the date; this way, you can get the current price for new orders, and get the price for past orders based on the date.

select price, dateEffective from ProductDetails where productId = 1234567 and
dateEffective between date1 and date2;

You really don't want to create a bunch of separate tables for different time periods, and you really don't want to keep adding columns to the Product table every time details update.

  • Excellent! Much more simple, and less cluttered! Thanks for the approach.
    – Jose A
    Oct 6, 2014 at 20:32
  • You know, that now that I'm think a little bit more. I believe there's no need to use a date to develop this situation. With th
    – Jose A
    Oct 8, 2014 at 15:39
  • You know, now that I'm think a little bit more about it. I believe that there's no need to use a date to develop this situation and at the same time, implementing yours and DougM's approach. I can always link the ProductDetails table to the ProductProcess. Pt. 1/2
    – Jose A
    Oct 8, 2014 at 15:46
  • Pt. 2/2 Example: I add a column called "ProductDetailsID" to the ProductProcess table. Then, that ProductDetailsID will refer to the ProductDetails table. Since each new product will always have the last value, I could always look in the ProductDetails table using the productID and sorting it using "DESC" modifier. And old products will still be linked to the old values.
    – Jose A
    Oct 8, 2014 at 15:46

If you have one thing, which has some attributes which cannot change and others which may change over time, you really have two separate things. And that means you should consider giving each "thing" its own table.

Neither of your options use the database model to make anyone's job easier. Selecting entirely different tables is an annoying practice, but occasionally needed as an implementation concern for very large data sets. Selecting different columns is a TERRIBLE idea, that screams out for further normalization.

Use a separate table for prices, with either date ranges or a "current or closest in the past" model. Anything else is a headache that you should avoid unless you have a very good reason not to.


A clean design is if you have a startDate and endDate for every price:

for a new product:

  • insert into price set product=X, startDate=now(), endDate=infinity

for a price change:

  • insert into price set product=X, startDate=now(), endDate=infinity
  • insert trigger fires: update price set endDate=now() where product=X and endDate=infinity

This way you can also easily model periods when there is no price.

Advanced: This can also be used for logging prices, so the real current price is in one table and you just update it and the logging table gets automatically filled by a trigger with the startDate and endDate as described above.

  • Wouldn't it be better, instead of setting the endDate as infinity, or using another column, I can always trigger the new date as the endDate of the previous date (I know it's kind of tangling, but I did understand what you meant!).
    – Jose A
    Oct 8, 2014 at 15:16

Alternately , you can keep a price column in order details table. Like in my case, I have a order details table where I keep the record of customer , product and order # .. here I'm saving price with all order details and yes I can edit that price for particular order.


Before you start any work in the database, you verify what functionality your sales people want. My assumption would be: For historic purchases, you store product, quantity and historic price. In your product database you store the current price, and an optional future price with start date.

So you always have the right price for refunds. Sales can enter price changes ahead of time. When you read a price, you check if there is a “future” price that is now in the past, and in that case make it the current price. Plus you need some cleverness to make sure you don’t charge more than the displayed price when customers buy around the time of the price change. What’s helpful is to always make changes at 3:30am when nobody is buying.

Not the answer you're looking for? Browse other questions tagged or ask your own question.