Forum Moderators: open
I know that Normalization can be confusing, so I am trying to be as clear as I can here. I appreciate any/all assistance that anyone can give.
****************
I have a couple hundred different products for a jewelry line. Around half of those products come in various sizes, which means I've got around 2,500 unique "SKUs" (Stock Keeping Unit).
Each SKU will have one product, but a product may have many SKUs associated. So I believe my 'central' table is going to be the 'SKU' table.
A product may have multiple categories. Originally I was going to put multiple categories into one field and the 'explode' the results (1¦3¦5), but that doesn't jive with 'normalization'.
I didn't take out size into its own table thinking I would just put "N/A" under items that do not have sizes, but I'm not sure that is proper.
I can't figure out if I've gotten this to where it needs to be, or if I need to take it further. I'm not sure how to properly connect these tables, or how/where to place the foreign keys.
Any help would be greatly appreciated!
****************
SKU
----------
SKU ID
SKU Name
SKU Description
Price Adjustment (Certain Sizes cost more than the "Base Price")
Size
Products
----------
Product ID
Weight
Name
Description
Part Number
Base Price
Introduction Date
Active?
Categories
----------
Category ID
Name
Parent ID (To deal with the issue of Sub-categories)
The relationship between Products and Categories is many to many (products can have many categories and categories can have many products). Therefore, you need to add a join table that has Category ID and Product ID as a compound primary key.
The problem with Size can be solved by having the column allow NULLS
You're doing pretty well here I think but I'm a little unclear on something.
Each SKU will have one product, but a product may have many SKUs associated.
Can you give a specific example of SKU's / products?
I.e. is a SKU a certain diamond while a product is a ring with a diamond in it?
[edited by: engine at 10:00 am (utc) on Jan. 17, 2010]
[edit reason] Tidied up [/edit]
I've done some additional work on it and I've got something I *think* may work, but I'd really like a second opinion. I'm new to database design, and I want to get it right.
I made a image of the database layout, but I don't think I am allowed to link to an image... is that right?
So here it is in text format, as best I know how to display it. Sorry if I am not using standard conventions, I am new to this.
Thank you in advance for any help you can provide. I really appreciate it.
Table Layout
"Size" 1 --- M "SKU"
"Products" 1 ---- M "SKU"
"SKU" 1 ---- M "SKU_Category"
"SKU_Category" M ---- 1 "Category"
Each individual table:
Size
------
Size_ID
Size
Products
------
Product_ID
Product_Name
Product_Description
Product_Number
Product_ID
BasePrice
IntroductionDate
Active
Weight
SKU
--------
SKU_ID
SKU
SKU_Description
PriceAdjustment
Size_ID
Product_ID
SKU_Category
---------
SKU_Category_ID
SKU_ID
Category_ID
Category
---------
Category_ID
Category_Name
ParentID
This has been discussed quite a few times, see links below. I think you may be on the wrong track. Look at this:
Size_ID
Size
What if the "option" is not always size? What if, say, you have a ring with various colors of gemstones, and the only thing different is the color and SKU? I have answers below . . .
The one thing I see that's on the right track is
PriceAdjustment
Which is easy to manage. If a price exists in "priceAdjustment" (better named "option_price," below) this takes precedence over the base price in the products table. Furthermore, you are going to need another field, "required option." That is, if it's a required option to select this product, such as size, color, if there is a price here, it overrides the base price, otherwise it's an "add on" and increases the base price if selected ("same ring but with 3 stones, same ring but with four stones.")
Boiling it down, you have two main elements: products and options. these options can be anything - size, color, # stones, metal type, whatever. And you should be able to add options at any time, and the option types should be unlimited, as well as the option values.
You **might** reduce your database size by doing a lookup for existing options and implementing them, like
table option_types
rec_id¦option_name
1¦Size
2¦Color
3¦Stone
4¦Metal
So that you have a small table for these names. Examples, this might only contain size, color, stone, metal . . . then you would have
table option_values
rec_id¦option_type_id¦option_value
1¦2¦Red
2¦2¦Green
3¦2¦Blue
4¦4¦Gold
5¦4¦Silver
6¦3¦Diamond
Now we get to it: the options table. There are a couple things to note about this.
- You can have **unlimited**, or zero options for any given product
- You can have **unlimited**, or zero option values for any given product
- Your option table values are all numeric, making it light speed faster than text lookups
- The values are often "recycled" from the short and sweet option types and option values tables
The down side, which really isn't one: this is going to make for some pretty complex joins in your selects.
So a simple scenario:
products
rec_id¦product_id¦title... etc.
options
rec_id¦product_id¦sku¦option_type¦option_value¦required¦option_price
1¦123¦AZ123¦2¦1¦1¦0.00
Our "single product" with ID 123, is a ring with a color option of blue, and blue is a required selection, but it does not alter the base price. You would have multiple rows for this product to select size, etc.
It may be difficult to get your head around this, but the worst thing you can do is try to predict the option types you will have - this locks you in and once done, you're stuck with reprogramming it for "exceptions." Program for them now. :-)
Some more examples I've posted on this very topic, and only slight variations in approach:
Hammers and Nails [webmasterworld.com]
The unflappable Widget [webmasterworld.com]
Someone who comes back to a thread in a year that is crucially helpful to them may find that the "key" is in the image, and the link to that image is dead. I think we've all been there and realize how frustrating that is... I've even done that a few times on other forums where it was *my* link that I let die.
It takes a bit more work to talk it all out, but it helps a lot more people down the road. :)
I have 5 Tables. SKU, Product, Options, Option_Type, Option_Value.
Table SKU has a relationship with Products and Options. There are many SKUS and each sku will have exactly 1 product, but might have many options.
The product table is only connected to the SKU table. It lists the name, description, price, etc..
The Option table is then related to two other tables. Option_Type and Option_Value. I'm not comfortable with the way this is linked to SKU, I think I might have it incorrect. Am I going too crazy here with Foreign Keys?
Listed out we have:
SKU
-----------
SKU_id(index)|SKU|SKU_description|product_id(fk)|option_id(fk)
Products
-----------
product_id(index)|product_name|product_description|product_number|base_price|intro_date|weight|active|
Options
-----------
option_id(index)|option_type_id(fk)|option_value_id(fk)|sku_id(fk)|price_adj|
Option_Type
-----------
option_type_id(index)|option_name
Option_Value
-----------
option_value_id(index)|option_type_id(fk)|option_value
Thank you so much for anyone taking time to help me think this through.
The one things I see, and am not sure about, is the management of SKU's.
There are many SKUS and each sku will have exactly 1 product, but might have many options.
So you are saying, different options do not affect the sku? Isn't the SKU a unique identifier in terms of cataloging? (not in terms of your database.)
There are two veins of thought here:
widget large blue SKU W001LB
widget large red SKU W001LR
widget large yellow SKU W001LY
It seems like this is the best case, as it allows you to uniquely locate a product variation by the unique SKU. W001LR identifies the widget W001 in the variation of large and red, different than the other widgets.
In this scenario, I maintain you'd have an SKU in both the products table and the product options table, which SKU is applied to the purchase is dependent on what they select. Returning to your original post,
Around half of those products come in various sizes, which means I've got around 2,500 unique "SKUs" (Stock Keeping Unit).
Following the above train of thought, size is an option, like # of stones or color. So I am still seeing these as one product, it's the option that has the unique SKU. So I'd probably dispense with the SKU table, move the SKU into the option for this product. If there's no "base SKU," leave it blank.
The other idea, as you've laid out, no unique SKU for varying options. I can't get my head around how you'd easily identify an option selection. For example, someone orders W001 in large and blue. So you'd have to store these in the purchase tables somehow. What you will have to do, then, is store the selected product options in the purchase, probably a related table, to look them up each time you need them.
With a unique SKU for each product combination, you'll only have to store a single value in the purchase table, the SKU. Without that, you'd need a relational table for selected options, which might complicate your selects a bit more.
At any rate, if the above is true and works for you, one SKU for each product, I don't see a need for a separate SKU table, I'd just put it in the products table.
So I'd probably dispense with the SKU table, move the SKU into the option for this product.
I have some products do not have sizes and thus there are no 'sub-skus'. Widget A doesn't come in any shapes or sizes so the 'product id' from the manufacturer and the 'sku' are the same. SKU is W001 AND Product Number is W001. That is it.
There are a number of widgets that DO have options though. This manufacturer at this time ONLY has one option of Size, but I take your earlier point and I do want to set this up so that if in the future they add a new option, I can add it without a complete redesign.
The issue I have some products do not have sizes and thus there are no 'sub-skus'
So I'd probably dispense with the SKU table, move the SKU into the option for this product.
My original though was to maybe have a "QOH" field in the SKU table... is that not the correct way to think of it?