tags:

views:

39

answers:

2

For an e-shop I have

  • Products table (id, name, price, description)
  • Attributes table (attribute name, attribute value, product_id_fk)

Attribute name examples include: size, color and Attribute value examples include: XL, L, red, blue.

What is the best way to store stock levels? A "Bag" product may be in stock in L / red but not in XL / red whereas it may be in stock for all sizes in blue. There may be more than 2 attributes per product.

A third table is definitely needed. I think the best way to go is to have one column per attribute and an additional column for the product_id_fk. This would mean that if a new attribute is added for whatever product, an additional column needs to be created in the Stock table

Or is there a better way?

+2  A: 

It looks as though you have a many-to-many relationship (i.e., products can have many attributes, and attributes can be associated with many products). Therefore your best design is to have a relationship table that contains the ids of both the product and the attribute.

products (id, name, price, description)
attributes (id, attribute name, attribute value)
product_attribute (product_id (PK,FK), attribute_id (PK,FK)) 

This works if you have a unique row for each physical item. If you don't then you need to have something that can handle the different types of the product.

product (id, name, price, description)
product_type (id, product_id (FK), count)
attributes (id, attribute name, attribute value)
product_attribute (product_type_id (PK,FK), attribute_id (PK,FK))

PK = Primary Key FK = Foreign Key

Justin Giboney
Could you explain this pseudo syntax? (product_id (PK,FK), attribute_id (PK,FK))
stef
If I'm not mistaken this setup would allow me to manage the stock for a red bag but not a red XL bag? In the product_attribute I'd need multiple attribute_id values (size, color). Right?
stef
The two setups will work depending on what you carry. The top one would be best for unique products such as cars.If your working with hand bags, the bottom one would better suit your needs. You would have a product_type for red small bags a product type for red XL bags and so on. Because of this you may want a description column in the product_type table as well.This is better than trying to create a column for each unique type of bag as you will shortly find yourself running out of columns and it will mess things up later.
Justin Giboney
So does your product_attribute table in the bottom solution have 4 cols or 2 ?
stef
Also: "You would have a product_type for red small bags a product type for red XL bags and so on". If I sell the same backpack in 4 different sizes and 10 different colors, I'd have to "create a new product" 40 times?
stef
product_attribute has 2 columns. It is an association table just representing the connection between the two.
Justin Giboney
If every size (4 of them) can be connected to every color (10 of them) then, yes, you would have to create 40 product_types. If you do it your way, you'll have to create 40 columns in your third table. To create one table with every possible size/color/other combination will create a very large table.
Justin Giboney
Just thinking about it, if your hand bag can have a gold or a silver chain, then you'll have size/color/metal combinations creating 80 columns in your table.
Justin Giboney
A: 

Why not create a table like this:

show create table product\G
*************************** 1. row ***************************
       Table: product
Create Table: CREATE TABLE `product` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) NOT NULL,
  `price` float NOT NULL,
  `color` enum('red','blue') NOT NULL,
  `size` enum('L','XL') NOT NULL,
  `stocklevel` int(11) NOT NULL,
  `description` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1

Sure, this has a finite number of attributes, but it is not hard to alter the table to add additional attributes as necessary.

For example, to add additional color types:

ALTER TABLE product MODIFY COLUMN `color` ENUM('red','blue','green') AFTER `price`;

and to add an additional attribute:

ALTER TABLE product ADD COLUMN `condition` ENUM('good','bad','ugly') AFTER `size`;

By the way, I think the attributes table has a problem. A product can have attributes (red and L), but (L and XL) would not make any sense. The attributes table does not stop such data from being entered. I think the true attributes are not red,blue,L and XL but rather color and size.

unutbu
I was thinking about the attributes as well. The only reason for the attributes table is to hold a value that can be shared among products (e.g., add $4 for an XL). This table doesn't have that ability, but you may not need it. Another thing to think about with this is that the products won't share a description. You'll have to enter the description each time. If you want to change the description, you have to change it for all of them. Other than that, this is a good solution.
Justin Giboney
@Justin: Oh! LOL, I was wondering what an attribute value was for... :) And yes, I agree using a text description column is probably not right. Perhaps stef could store the descriptions in a separate table, and associate them with products with a foreign key...
unutbu
There is another issue to think about with this. That is if you are entering a product that is not a hand bag, that doesn't use either color or size or both, then you have to enter NULL values, which isn't usually considered best practice, but acceptable if required.
Justin Giboney
In the table you have in the MySQL command I'd have to add multiple rows per product (and duplicate the product) just to reflect that multiple sizes and colors exist. No ideal I think ...
stef
@Justin: Why is having NULL values frowned upon?
unutbu
I guess NULL values are frowned upon cause it "wastes space" but is very far form unacceptable in this scenario IMHO
stef
In my experience it causes problems in front end systems (http://stackoverflow.com/questions/271888/best-practice-for-handling-null-strings-from-database-in-java) and can take up space with certain databases (http://vyaskn.tripod.com/coding_conventions.htm). In my opinion it shows poor design as it reserves a spot that you know will not be used.
Justin Giboney