Constraint spanning several tables

database-design

Imagine the following tables:

Products (Id, Name, …)

Used for storing products

ProductVersions (Id, Version, ReleasedOn)

Used for storing a version history of a single product (v1.0, v2.0, v3.0, …)

Customers (Id, ForeName, …)

Well, yeah. Used for storing customers.

Now a single customer can have multiple products. That requires another table:

CustomerProducts (Id, CustomerId, ???)

What is the best approach here? Should I reference to the Products table (ProductId) or the ProductVersions table (ProductVersionId)?

In terms of joining I'd have access to the Product entity when querying over the ProductVersion of a customer (Customer -> ProductVersion -> Product)

I know it is dependant on my very own design (so if a user owns a product or a version of a product), but what's the best way in general? What if a user can own an entire Product (Product1), but only owns Version 3.0 of Product2?

Best Answer

On product what you have is a Type 2, Slowly Changing Dimension.

A More in-depth discussion on Slowly Changing Dimensions here

A model for this would look something like the following: enter image description here

Customer stays as is.

Product has a hierarchy (self referencing to the parent [previous version] Product has a different ProductId for each version.

You did not mention whether multiple versions are valid at the same time. Let us assume not.

Valid_From:Valid_To are one way to identify when a product is valid. The 'current' product version has the valid_from set, but valid_to NULL.

When it is time to move to the next 'Version':

  1. Update the current records Valid_To date timestamp to now()
  2. Get the next ProductId (nextval on a sequence ususally)
  3. Get the next Version number (derived from the current version number)
  4. Insert new record into Product, valid_From to now(), use new version number, reference the old parentId in the Parent_prodid
  5. Commit

You will get new ProductIds for each version, but you will be able to give details of the product/customer relationship over time.

'ownership' of a product may be assigned at any version number. You can cascade the ownership from by maintaining the appropriate CUST_PRODUCT entries, they can be singular (for a specific version) or multiple for all or a subset of the versions.

You can find all versions by cascading thru the self referencing structure until you get the first (oldest, smallest version number, ...)

Related Question