I am modeling a database for a webshop and have come across ad issue. Basically the question is whether to ignore database normalization rules for simplicity's sake. Below is the relevant part of my diagram prior to the issue. Database diagram Basically, the product can have options (size, flavor, color) but only from one option group. Since an option group can have many options and a product that uses it can take a subset, a ProductOption table is created. Next we have a SpecialOffers table. Next, a special offer can have many products and products can belong to many special offers, hence the association table SpecialOfferProducts. All this works fine until the special offer includes a product that has options. This is where I run into problems. I have a couple of ideas.
First idea: Create an association table between SpecialOfferProducts and ProductOptions. I don't like this idea since both tables have composite primary keys and creating a table that has a composite primary key composed of two composite primary keys seems really weird and I have never seen anything like it.
Second idea: Create a association table between SpecialOfferProducts and Options. This seems wrong since Options is not directly tied to Product. Still this would work and the primary key would be a little simpler.
Third idea: This is the one that I like the most but it violates a few rules. Change the SpecialOfferProducts table. Make it have its own primary key and have SpecialOffers, Products and Options as foreign keys. Simply make the Options foreign key nullable and problem solved. Of course the problems are that I am not making an association table where I should and am making a foreign key nullable. This would slightly complicate my code to deal with all of this but I still feel that this is much simpler than the other approaches since I reduce the number of composite keys and I don't have to add another table in the case where the product in a special offer uses an option.
My question is, which one of this options is best? Is there a better option I have not mentioned?
Using Martin style notation
OptionGroups has (0,n) relationship with the table Options. Options has (1,1) relationship with the table OptionGroups. The purpose of these table is to store information like color, size, etc. An example wouldbe OptionGroups entry color that has Option entries black, white, etc.
Product table has (0,1) relationship with table OptionGroups. OptionGroups has (0,n) relationship with table Product. Product table has a (o,n) relationship with the table Options. Options table has a (o,n) relationship with the table Product. Many-to-many relation produces association table ProductOptions. ProductOptions has a composite PK ProductID, OptionsID. The purpose of these tables is to allow product to have (but does not have to have) options from a certain option group but does not need to have all options from that group.
Example 1. Product does not have any options, hence FK Product_OptionGroups is null. In this case the product does not have any entries in the ProductOptions table.
Example 2. Product has options (lets say color) and so the FK Product_OptionGroups is not null (has the ID of the coresponding option group). Option group color can have many colors and the product is allowed to use one or many of those colors. The colors in use by the product are entries in the table ProductOptions.
SpecialOffer table has a (1,n) relation to the table Products. Products table has a (0,n) relation to the table SpecialOffer. Many-to-many relation creates the association table SpecialOfferProducts. This table has a PK SpecialOfferID, ProductID. The table has a Quantity attribute indicating the quantity of the product.
Example. SpecialOffer A includes one instance of Product A and two instances Product B.
Lets say that the Product A has options. Now SpecialOfferProducts table must reference the correct option.(maybe the product can be blue and red and the special offer only includes the red product). This is where the current schema does not work and either an additional table must be introduced (idea 1 and 2) or the existing tables changed (idea 3).