Reputation: 53
I'm trying to build a price comparison database with n products and a definitive but changing number of vendors that sell these products.
For my price comparison database, I need to store both current prices for a product across different vendors and historical prices (one lowest price).
As I see it, I have 2 options to design the database tables:
1. Put all vendor prices into the main table.
I know how many vendors there will be and if I add or remove a vendor I can add or remove a column.
Historical prices (lowest price on certain date across all vendors), goes into a separate table with a product name, a price and a date.
2. Have one table for products and one table for prices
I will have only the static attribute data in the main table such as categories, attributes etc and then add prices to a separate product table where I store price, vendor, date in it and I can store the lowest price as a pseudo-vendor in that table for each date or I can store it in a separate table as well.
Which method would you suggest and am I missing something?
Upvotes: 2
Views: 1123
Reputation: 63
Implementing Option 2 with a Database Schema Example
Here's a simplified schema:
Products Table: Stores static product data.
Prices Table: Stores current and historical prices.
Vendors Table:
SQL Example for a Trigger to Record Lowest Historical Price
CREATE TABLE historical_prices (
product_id INT,
price DECIMAL(10, 2),
date DATE,
PRIMARY KEY (product_id, date)
);
DELIMITER $$
CREATE TRIGGER update_lowest_price
AFTER INSERT ON prices
FOR EACH ROW
BEGIN
DECLARE lowest_price DECIMAL(10,2);
-- Check for existing lowest price on the same date
SELECT price INTO lowest_price FROM historical_prices
WHERE product_id = NEW.product_id AND date = NEW.date;
IF lowest_price IS NULL OR NEW.price < lowest_price THEN
-- Insert or update the historical_prices table
INSERT INTO historical_prices (product_id, price, date)
VALUES (NEW.product_id, NEW.price, NEW.date)
ON DUPLICATE KEY UPDATE price = LEAST(price, NEW.price);
END IF;
END$$
DELIMITER ;
Upvotes: 0
Reputation: 1269873
You should store the base data in a normalized format that contains all the history. This means that you have tables for:
products
, with one row per product and the static information about the products.vendors
, with one row per vendor and the static information about the vendor.prices
, with one row per price along with the date and product and vendor.You can get the current and lowest prices using a query, such as:
select pr.*
from (select pr.*, min(price) over (partition by product) as min_price
row_number() over (partition by product, vendor order by price_datetime desc) as seqnum
from prices pr
where pr.product_id = XXX
) pr
where seqnum = 1;
For performance, you want an index on prices(product, vendor, price_datetime desc)
.
Eventually, you may find that this query runs too slowly. In that case, you will then consider optimizations. One optimization would simply be storing the latest date for each price/vendor combination using a trigger, along with the minimum price in the products
table -- presumably using triggers.
Another would be maintaining a summary table for each product and vendor using triggers. However, that is probably not how you should start the endeavor.
However, you might be surprised at how well the above query can perform on your data.
Upvotes: 1