Best Way to Design These Tables - mysql

Part of my schema for a travel project has the following tables
Cruises
Flights
Hotels
CarParking
I need a container that wraps one or more of these products into a package. One Cruise/Hotel etc might be part of many packages. I initially thought of
Package
- PackageId
- Etc
PackageItem
- PackageItemId
- PackageId (fk)
- ItemId (fk)
- ItemType
Where ItemType would indicate whether it's a Cruise, Flight, Hotel etc. I suppose I could use Triggers to enforce referential integrity.
My other idea was
Package
- ...
PackageItem
- PackageItemId
- PackageId (fk)
- CruiseId (nullable fk)
- FlightId (nullable fk)
- HotelId (nullable fk)
- CarParkingId (nullable fk)
- etc
I suppose each has it pros and cons, but I can't decide. Which do you think is better, which would you choose if you had to implement something like this?
Database is MySql. Platform is C# MVC ASP.NET
(I did search and there were a few similar questions but nothing that corresponded all that well)

The first option is the most flexible. And I tend to go with flexibility.
Advantage: Common Queries
If you want a report on cruises, the query is the same as one for hotels, but with a different WHERE clause.
Using the second form you need to join on and select from different tables.
*Advantage: Growth without Schema Changes
If you need to add Excursions to your model (something that can certainly have many associated to a single package), you just create a new Excursions type.
Using the second form you need to add new fields to your tables, creates new tables to hold the data, and update your queries and logic to use those new tables and fields.
Cost: Data moving to a form not friendly for human digestion
Many people could legitimately say that this shouldn't matter at all. I say that it matters in so far as you have to take account of it...
- It can make debugging harder, so you need to be more regimented and methodical
- It means your GUI has to be smarter in transforming your data for display
Also, although this is a cost, it has the benefit of forcing you into a mid-set where you are less likely so make simplistic assumptions and make sloppy mistakes. This is a cost that I like to have.
Falacy: Constraints can't be enforced
Constraint - Each package component must be either Hotel, Packing, Flight or Cruise
Method - Have a component_type table, and FK to that table
Constraint - Only one of each type allowed per package
Method - UNIQUE constraint on (package_id, component_type_id)
Constraint - Each component can only be within one package
Method - UNIQUE constraint on (component_id)
Cost - Deferred complexity
In my opinion, the normalised table to map Packages to Components is actually simple and elegant. The next step, is to decide how to store the associated details of a component.
A single global "component" table could hold all the fields, but allow them to be nullable. Thus a HOTEL would have a NULL Flight_Number. But all components would have a Price.
Or you could create an Entity_Attribute_Value table. This can be formed in such a way as to prevent hotels having a flight number...
- component_attributes table = (id, type_id, attribute_id, attribute_value)
- (type_id, attribute_id) can be foreign keyed to allowable combinations
It's impossible (afaik) to enforce REQUIRED fields, such as Price.
The Value is often stored as a VARCHAR.
For that reason, and others, search the data by Value becomes hard.
final opinion
I would not use option 2, as this is highly constrained and merges two considerations together - How to hold data for different component types (hotels, flights, etc) and how to relate them to their parent packages.
I would instead recommend that you consider the multitude of ways for holding the component data, and make that decision based on your needs. Then relate those components to the packages using a 1:many normalised mapping table. Your option 1.

You haven't mentioned in question whether you need to support multiple products of same type inside a single package - i.e. whether package can contain multiple Hotels, for example.
1) If support for multiple same-type products per package is required then you should go first way, but maybe split relationships into separate tables per product type, i.e.
PackageHotelItem
- PackageItemId
- PackageId (fk)
- HotelId (fk)
PackageCruiseItem
- PackageItemId
- PackageId (fk)
- CruiseId (fk)
... etc.
This way you will be able to have referential integrity via normal FK mechanism.
2) If you don't need such support then you may use your second solution.

Related

INSERT based on the relationship between the types of entities to be inserted?

I can't find a term for what I'm trying to do so that may be limiting my ability to find info related to my question.
I'm trying to relate product identifiers and product processing codes (orange table in fig.) with validation against what product types and subtypes are valid for each process code based on process type. Importantly, each product identifier is related to a product type (see ProductIdentifier table) and each process code is related to process type (see ProcessCode table). I minimized the attributes in the tables below to only those necessary for my question.
In the above example, when I INSERT INTO the RunProcessTypeOne table, I need to validate that the ProductCode for RoleOneProductIdentifier is present in ProductTypeTwo. Similarly, I need to validate that the ProductCode for RoleTwoProductIdentifier is present in ProductSubtypeOne.
Of course I can use a stored procedure that inserts into the RunProcessTypeOne table after running SELECT to check for the presence of the ProductCode related to RoleOneProductIdentifier and RoleTwoProductIdentifier in the relevant tables. This doesn't seem optimal since I'm having to run three SELECTs for every INSERT. Plus, it seems fishy that the relationship between ProcessTypes and ProductCodes would only be known within the stored procedure and not via relationships established between the tables themselves (foreign key).
Are there alternatives to this approach? Is there a standard for handling this type of validation where you need to validate individual instances (e.g. ProductIdentifiers) of entity types based on the relationships between those types (e.g. the relationship between ProductTypeTwo and ProcessTypeOne)?
If more details are helpful: The relationship between ProductCode and ProcessCode is many-to-many but there are rules that define product roles in each process and only certain product types or subtypes may fulfill those roles. ProductTypeOne might include attributes that define a specific kind of product like color or shape. ProductIdentifier includes the many lots of any ProductCode that are manufactured. ProcessCode includes settings that are put on a machine for processing. ProductType by way of ProductCode determines if a ProductIdentifier is valid for a particular ProcessType. Individual ProcessCodes don't discriminate valid ProducIdentifiers, only the ProcessType related to the ProcessCode would discriminate.
it seems fishy that the relationship between ProcessTypes and ProductCodes would only be known within the stored procedure and not via relationships established between the tables themselves (foreign key).
Yes that's an important observation, good to see you questioning the current schema. The fact of the matter is that SQL is not very powerful when it comes to representing data structures. So often a stored procedure is the only/least worst approach.
I'll make a suggestion for how to achieve this without stored procedures, but I won't call it "optimal": there's likely to be a performance hit for INSERTs (and worse for UPDATEs), because the SQL engine will probably be in effect carrying out the same SELECTs as you'd code in a stored procedure.
Split table ProductIdentifier into two:
ProductIdentifierTypeTwo PK ProductIdentifier, ProductCode FK REFERENCES ProductTypeTwo.ProductCode.
ProductIdentifierTypeOne PK ProductIdentifier, ProductCode FK REFERENCES ProductTypeOne.ProductCode.
Also CREATE VIEW ProductIdentifier UNION the two sub-tables, PK ProductIdentifier. This makes sure ProductIdentifier isn't duplicated between the two types.
IOW this avoids the ProductIdentifier table directly referencing the ProductCode table, where it can only examine ProductType as a column value, not as a referential structure.
Then
RunProcessTypeOne.RoleOneProductIdentifier FK REFERENCES ProductIdentifierTypeTwo.ProductIdentifier.
RunProcessTypeOne.RoleTwoProductIdentifier FK REFERENCES ProductIdentifierTypeOne.ProductIdentifier.
Making the original ProductIdentifier a VIEW is the least non-optimal way to manage updates (I'm guessing from your comment): ProductIdentifiers are less volatile than RunProcesses.
Re your more general question:
Is there a standard for handling this type of validation where you need to validate individual instances (e.g. ProductIdentifiers) of entity types based on the relationships between those types (e.g. the relationship between ProductTypeTwo and ProcessTypeOne)?
There are facilities included in the SQL standard. Most vendors haven't implemented them, or only partially support them -- essentially because implementing them would need running SELECTs with tricky logic as part of table updates.
You should be able to CREATE VIEW with a filter to only the rows that are the target of some FK.
(Your dba is likely to object that VIEWs come with an unacceptable performance hit. In this example, you'd have a single ProductIdentifier table, with the two sub-tables I suggest above as VIEWs. But maintaining those views would need joining to ProductCode to filter by ProductType.)
Then you should be able to define a FK to the VIEW rather than to the base table.
(This is the bit many SQL vendors don't support.)

How to structure a Bill of Materials that has multiple options

I am stuck trying to develop a Bill of Materials in Access. I have a table call IM_Item_Registry where I have the Item_Code and a boolean for if it's a component. Where I'm stuck is that past sins of the company made several part numbers for the same ingredient from different vendors. A product may use ingredient 1 at the beginning of the run and ingredient 2 at the end of a run depending on inventory and it may switch from job to job (Lack of discipline and random purchasing based on price). It's creating a headache for me because they typically have different inclusions. How would I go about adding in the flexibility to use both? or would it just be easier to make multiple versions and then select those version upon scheduling?
I know this is loaded and I can include more detail if needed but I appreciate your help I've been researching on how to do this for a couple weeks now.
EDIT (3/28/2019)
this is for an injection molding company.
IM_Item_Registry (Fields: Item_Code, Category(Raw, manufactured, customer supplied, assembly component), Description, Component (boolean), active (boolean), Unit of Measure.
for this Bill-of-materials 100011 produces component lets call this a handle. bill 100011 uses raw resin 700049 at 98% inclusion and raw color 600020 at 2% inclusion. However, we may run out of raw color 600020 and have to run it out of 600051 which would change 700049 to 98.5% inclusion because 600051 requires 1.5% inclusion to achieve the same color.
i would like to create a table that would call out for the general term lets say 600020 and 600051 is yellow color additive. then create a "ghost" number to call for either 600020 or 600051 and give both formulation recipes. When production starts they would scan in which color they actually used to create the production BOM themselves and record which color was used and how much. is there a way to do this in access database structuring?
I'm assuming I would need both the item_registry table, a BoM table (fields: BOM#, ParentID, Ghost_ID) and then a components table (Fields: Ghost_ID, item_code, Inclusion Rate).
Database normalization is the guiding principle for designing efficient, useful tables and relationships in a relational database. Access forms, subforms, reports, etc. require properly normalized tables to work as intended. There are various levels of normalization, but the common idea is to avoid duplication of data between rows and columns of data. Having duplicate data requires a lot of overhead in storage and in ensuring that actions on the database do not create inconsistent states (contradictory data values). Well-normalized tables allow useful constraints to be defined between data columns and/or rows to ensure that data is valid.
The [BoM] table as proposed in the question is not normalized. But before we get to that, the ParentID was not defined and it's not clear what it represents. Instead, to help show why it's not normalized, let me add a [Product] column to the [BoM] table. Then if such a handle has two alternative lists of components (ghosts?), the table would look like
BOMID, Product, GhostID
----- ------- -------
1 Handle 1
1 Handle 2
See the duplication? And now if the product is renamed, for instance to "Bronze Handle", then both rows need to be updated for a single conceptual element. It also introduces the possibility of having contradictory data like
BOMID, Product, GhostID
----- ------- -------
1 Handle 1
1 Bronze Handle 2
Enough said about that, since I've already gone on too much about normalization concepts here. Following is a basic normalized schema which would serve you better, but notice that it's not too much different that what you proposed in the question. The only real difference is that the BoM table is normalized by splitting its columns (and purpose) into another table.
I do not list all columns here, only primary and foreign keys and a few other meaningful columns. PK = Primary Key (unique, non-null key), FK = Foreign Key. Proper indices should be defined on the PK and FK columns AND relationships defined with appropriate constraints.
Table: [IM_Item_Registry]
Item_Code (PK)
Table: [BOM]
BOMID (PK)
ProductID (FK)
Table: [BOM_Option]
OptionID (PK)
BOMID (FK)
Primary (boolean) - flags the primary/usual list of components
Description
Table: [Option_Items]
OptionID (FK; part of composite PK)
Item_Code (FK; part of composite PK)
Inclusion_Rate
The [BOM].[ProductID] column alludes to another table with details of the product which should be defined separately from the Bill of Material. If this database really is super-simplistic, then it could just be a string field [Product] containing the name, but I assume there are more useful details to store. Perhaps this is what the ParentID also alluded to? (I suggest choosing names that are not so abstract like "parent" and "ghost", hence my choice of the word "option".)
Really, since [BOM_Option] should be limited to a single option per BOM, it would fulfill proper normalization to create another table like
Table: [BOM_Primary]
[BOMID] (FK and PK) - Primary key so only one primary option can be defined at once
[OptionID] (FK)

DB design for one-to-one single column table

I'm unsure the best route to take for this example:
A table that holds information for a job; salary, dates of employment etc. The field I am wondering how best to store is 'job_title'.
Job title is going to be used as part of an auto-complete field so
I'll be using a query to fetch results.
The same job title will be used by multiple jobs in the DB.
Job title is going to be a large part of many queries in the
application.
A single job only ever has one title.
1 . Should I have a 2 tables, job and job_title, job table referencing the job_title table for its name.
2 . Should I have a 2 tables, job and job_title but store title as a direct value in job, job_title just storing a list of all preexisting values (somewhat redundant)?
3 . Or should I not use a reference table at all / other suggestion.
What is your choice of design in this situation, and how would it change in a one to many design?
This is an example, the actual design is much larger however I think this well conveys the issue.
Update, To clarify:
A User (outside scope of question) has many Jobs, a job (start/end date, {job title}) has a title, title ( name (ie. 'Web Developer' )
Your option 1 is the best design choice. Create the two tables along these lines:
jobs (job_id PK, title_id FK not null, start_date, end_date, ...)
job_titles (title_id PK, title)
The PKs should have clustered indexes; jobs.title_id and job_titles should have nonclustered or secondary indexes; job_titles.title should have a unique constraint.
This relationship can be modeled as 1-to-1 or 1-to-many (one title, many jobs). To enforce 1-to-1 modeling, apply a unique constraint to jobs.title_id. However, you should not model this as a 1-to-1 relationship, because it's not. You even say so yourself: "The same job title will be used by multiple jobs in the DB" and "A single job only ever has one title." An entry in the jobs table represents a certain position held by a certain user during a certain period of time. Because this is a 1-to-many relationship, a separate table is the correct way to model the data.
Here's a simple example of why this is so. Your company only has one CEO, but what happens if the current one steps down and the board appoints a new one? You'll have two entries in jobs which both reference the same title, even though there's only one CEO "position" and the two users' job date ranges don't overlap. If you enforce a 1-to-1 relationship, modeling this data is impossible.
Why these particular indexes and constraints?
The ID columns are PKs and clustered indexes for hopefully obvious reasons; you use these for joins
jobs.title_id is an FK for hopefully obvious data integrity reasons
jobs.title_id is not null because every job should have a title
jobs.title_id needs an index in order to speed up joins
job_titles.title has an index because you've indicated you'll be querying based on this column (though I wouldn't query in such a fashion, especially since you've said there will be many titles; see below)
job_titles.title has a unique constraint because there's no reason to have duplicates of the same title. You can (and will) have multiple jobs with the same title, but you don't need two entries for "CEO" in job_titles. Enforcing this uniqueness will preserve data integrity useful for reporting purposes (e.g. plot the productivity of IT's web division based on how many "web developer" jobs are filled)
Remarks:
Job title is going to be used as part of an auto-complete field so I'll be using a query to fetch results.
As I mentioned before, use key-value pairs here. Fetch a list of them into memory in your app, and query that list for your autocomplete values. Then send the ID off to the DB for your actual SQL query. The queries will perform better that way; even with indexes, searching integers is generally quicker than searching strings.
You've said that titles will be user created. Put some input sanitation and validation process in place, because you don't want redundant entries like "WEB DEVELOPER", "web developer", "web developer", etc. Validation should occur at both the application and DB levels; the unique constraint is part (but all) of this. Prodigitalson's remark about separate machine and display columns is related to this issue.
Edited: after getting the clarify
A table like this is enough - just add the job_title_id column as foreign key in the main member table
---- "job_title" table ---- (store the job_title)
1. pk - job_title_id
2. unique - job_title_name <- index this
__ original answer __
You need to clarify what's the job_title going represent
a person that hold this position?
the division/department that has this position?
A certain set of attributes? like Sales always has a commission
or just a string of what was it called?
From what I read so far, you just need the "job_title" as some sort of dimension - make the id for it, make the string searchable - and that's it
example
---- "employee" table ---- (store employee info)
1. pk - employee_id
2. fk - job_title_id
3. other attribute (contract_start_date, salary, sex, ... so on ...)
---- "job_title" table ---- (store the job_title)
1. pk - job_title_id
2. unique - job_title_name <- index this
---- "employee_job_title_history" table ---- (We can check the employee job history here)
1. pk - employee_id
2. pk - job_title_id
3. pk - is_effective
4. effective_date [edited: this need to be PK too - thanks to KM.]
I still think you need to provide us a use-case - that will greatly improve both of our understanding I believe
If there are only a few fixed job titles you might want to use an enum in our database.
See http://dev.mysql.com/doc/refman/5.0/en/enum.html
If that's not supported by your version of mysql simply encode it with a numerical index and resolve it to a human readable form in your queries.

Database Normalization - I think?

We have a J2EE content management and e-commerce system, and in this system – for sake of a simple example – let’s say that we have 100 objects. All of these objects extend the same base class, and all share many of the same fields.
Let’s take two objects as an example: a news item that would be posted on a website, and a product that would be sold on a website. Both of these share common properties:
IDs: id, client ID, parent ID (long)
Flags: deleted, archived, inactive (boolean)
Dates: created, modified, deleted (datetime)
Content: name, description
And of course they have some properties that are different:
News item: author, posting date
Product: price, tax
So (finally) here is my question. Let’s say we have 100 objects in our system, and they all follow this pattern. They have many fields that overlap, and some unique fields. In terms of a relational database, would we be better off with:
Option One: Less Tables, Common Tables
table_id: id, client ID, parent ID (long) (id is the primary key, a GUID for all objects)
table_flag: id, deleted, archived, inactive (boolean)
table_date: id, created, modified, deleted (datetime)
table_content: id, name, description
table_news: id, author, posting date
table_product: id, price, tax
Option Two: More Tables, Common Fields Repeated
table_news: id, client ID, parent ID, deleted, archived, inactive, name, description, author, posting date
table_product: id, client ID, parent ID, deleted, archived, inactive, name, description, price, tax
For full disclosure – I am a developer and not a DBA, and because of that I prefer option one. But there is another team member that prefers option two, and I think he makes valid points.
Option One: Pros and Cons
Pro: Encapsulates common fields into common tables.
Pro: Need to change a common field? Change it in one place.
Pro: Only creates new fields/tables when they are needed.
Pro: Easier to create the queries dynamically, less repetitive code
Con: More joining to create objects (not sure of DB impact on that)
Con: More complex queries to store objects (not sure of DB impact on that)
Con: Common tables will become huge over time
Option Two: Pros and Cons
Pro: Perhaps it is better to distribute the load of all objects across tables?
Pro: Could index the news table on the client ID, and index the product table on the parent ID.
Pro: More readable to human eye: easy to see all the fields for an object in one table.
My Two Cents
For me, I much prefer the elegance of the first option – but maybe that is me trying to force object oriented patterns on a relational database. If all things were equal, I would go with option one UNLESS a DB expert told me that when we have millions of objects in the system, option one is going to create a performance problem.
Apologies for the long winded question. I am not great with DB lingo, so I probably could have summarized this more succinctly if I better understood terms like normalization. I tried to search for answers on this topic, and while I found many that were close (I suspect this is a common DB issue) I could not find any that answered all my questions. I read through this article on normalization:
But I did not totally understand it. On the one hand it was saying that you should remove any redundancies. But on the other hand, it was saying that each attribute should define only one object.
Thanks,
John
You should read Patterns of Enterprise Application Architecture by Martin Fowler. He writes about several options for the scenario you describe:
Single Table Inheritance: One table for all object subtypes. Stores all attributes, setting them NULL where they are inapplicable to the row's object subtype.
Class Table Inheritance: One table for column common to all subtypes, then one table for each subtype to store subtype-specific columns.
Concrete Table Inheritance: One table for each subtype, storing both subtype-specific columns and columns common to all subtypes.
Serialized LOB: One table for all object subtypes. Store common attributes as conventional columns, but combine optional or subtype-specific columns as fields in a BLOB that stores XML or JSON or whatever format you want.
Each one of these designs has pros and cons, so choose a solution depending on the most common way you access your data.
However, notice I use the word subtype above. I would use these designs only if the different object types are subtypes of a common base class. I'm assuming that News item and Product don't actually share a logical base class (besides Object); they are not subtypes of a common superclass.
So for the sake of OO design, I would choose Concrete Table Inheritance. This avoids any inappropriate coupling between these subtypes. There are columns the two tables have in common, but they basically amount to bookkeeping, not anything to do with the function of the class and hence the table.

DB design to store different products for each customer order

I'm building a simple way to insert customer orders into the db.
We have several products, each one needs different properties.
I've started designing the following tables:
CUSTOMER -> Order (FK to CUSTOMER) -> OrderItem (FK to Order)
Now I'm thinking How could I link product-specific tables to OrderItem.
Suppose I've two products: product1 (room_name, width, height, color) and product2 (number, width, height, type, optionals). I'd create two different tables and link them with the OrderItem, to get specific options, am I wrong? (of course there will be more than just two products)
How can I do this?
I'd have one Product table with a one-to-many relationship between OrderItem and Product. Put a FOREIGN KEY in the OrderItem table that points to its associated Product.
A design like yours would mean you'd have to add a table every time there was a new product. That would not do. You want to add products by inserting new rows.
No approach can resolve all of the issues you may be dealing with, the choice you make depends on which factor is most important to you.
Most people shirk away from having multiple tables. One reason is that you don't know how many tables you may end up with in the future. Another is that your queries may also bloat by having to join to multiple tables. And it may become a maintenance headache with multiple queries to update every time you add a table. Finally, adding a table is not even remotely as friendly as adding a record (Do you really want your App to be able to create tables?).
One option is just to add more and more fields to the Product table. By making the property fields NULLable, different products can use different fields.
But... You may then need to add logic to ensure that ProductX -always- has a value in FieldA, but that ProductY always has a value in FieldB, etc. And probably some meta-data about each product type so that your application knows which fields to use for which products. You still may need to add new fields, which is possibly tidier than adding new tables, but you still probably don't want the Application doing.
An option that totally avoids using DDL to add a product is to further normalise your data, and have the product-specific-properties in an Entity-Attribute-Value table. This is initially very attractive to many people as it is so generic and flexible.
Product(id, name, another-global-property, etc)
Product_Properties(product_id, property_id, property_value)
You'll probably have some meta-data and extra logic to ensure all the correct properties are used. But now you just add records to a generic structure whenever you create a new product.
But what type should "property value" be? It may need to hold strings, dates, numbers, anything. You could make it a string and use the meta-data to know how to CAST the value. Of you may have several value fields, one of each type, and a "field_type_id" or something to indicate which value-field should be read from.
It's also less friendly for certain searches. If you know a product_id, finding the properties is easy. If you want all products where the expiry date is in the past, you need to be careful about how you structure the data and indexes to make the query efficient. But if you want (expiry < today AND cost > 50) then you get a much different query from what you are used to - Each value is in a different ROW instead of a different FIELD.
Search performance really does begin to shrink as query complexity increases and design considerations become more technical.
Which way you go depends on application functional requirement, architecture and design decisions, and a good helpful dash of 'taste'.
You have tagged question as django. Then you should read this recent post:
Coding an inventory system, with polymorphic items and manageable item types
In this post #ThibaultJ explain how to accomplish this with Django model utils.
The idea is that you have a 'product' model and you inherit product1 and product2 from this model adding specific information for both. #ThibaultJ has posted intesting samples.
I will notice #ThibaultJ about this question. If #ThibaultJ writes an answer I will remove my post.
Here are some options
IMHO I would choose an Inheritance pattern, i.e. a new table called "ProductBase" with a unique Surrogate. Product base would have a classification e.g. "ProductType" which would then allow you to join into the appropriate 'subclass' Product table. OrderItem would reference just the Surrogate. Referential Integrity is enforcable, and it gives the opportunity for extending to additional forms of products. It does however require the use of a common unique surrogate amongst all Product table types. If there are other tables (other than OrderItem) referencing Product, it would also avoid the use of having to FK to composite keys.
Nullable Foreign Keys in OrderItem, i.e. OrderItem would have nullable FK to both (all) types of Product Tables, although only one of them would be present on each row.
By inner joining OrderItem to the appropriate Product tables would eliminate the 'wrong' product joins based on the NULLs. RI can still be enforced.
If you have the SAME type of Primary Key on all your Product subclass tables, then you could also add a single Product "Foreign" Key and a "ProductType" "Switch" on OrderItem. The problem here is that you can't enforce RI.
That said, I really wouldn't be creating a new table for each and every product - surely there are some broad 'categories' of Product which can be modelled in a uniform manner.
No doubt if you sell Aircraft and Groceries that you would probably need a AircraftProduct and a GroceryProduct, but surely A300, Boeing 747 and Cessna Skyhawk would fit as rows inside AircraftProduct, even if there are a few 'optional' nullable fields in each table not applicable to all products in this 'category'?
Edit : First see Dems and Duffmo's posts to see if you can avoid the requirement for having multiple Product tables at all, by using EAV / Multivalue / Metadata patterns to model Product.