I have an existing application that has the following entities in the database
- Customer
- InvoiceGroup
- SalesGroup
A customer can be part of multiple groups. Currently this is mapped in the following way
Customer table
- cid (Pk)
- fname
- surname
----
---
- invgrpdid (Fk)
- salesid (Fk)
Invoicegroup table
- invgrpid (Pk)
- name
- type
---
----
Salesgroup table
- salesid (Pk)
- name
- desc
-----
-----
I now have a requirement to add a new entity campaign. A Customer can be part of multiple campaigns. A campaign is deployed for a customer group which is created by
– selecting individual customers (custom) OR
– selecting an existing invoicegroup (invoice) OR
– selecting an existing salesgroup (sales)
The campaign customer list should be
– reusable, i.e can be used for multiple campaigns
– dynamic, i.e if created from an invoice/sales group, changes across the invoice and sales group
should be reflected to the campaign customer list
I am having difficulty designing for the dynamic requirement. I have come up with the following design, but it has exclusive arcs that is one key refering to multiple foreign keys which is not the recommended approach. I have thought of supertype and subtype, but I am not clear on designing the many-to-many relationships.
campaign
- campaignid(Pk)
- name
- startdate
- status
------
campaignlist
- listid(Pk)
- listname
- listtype - Invoice, Sales, Custom
- typeid (Fk) - Refers to invoicegroupid or salesgroupid depending on listtype
-----
customercampaign
- listid (Fk)
- customerid (Fk)
- status
- dateupdated
-------------
What would be a better approach to design this considering referential integrity and normalization.
The most frequent query run multiple times daily will be to retrieve all campaign information for a customer. So need to be mindful of multiple tables and joins.
At a first stab, I would do something like this:
That is, use table inheritance. This is quite a normalised design, which in my opinion is the approach to take when you’re not yet clued up on specific requirements. Optionally, you could make your life easier by denormalising a little and putting a
CampaignListTypeIDin theCampaignListtable. In this case though, it would be difficult to maintain the integrity of the data model without writing logic in a trigger.I’m assuming that you won’t ever have to do interesting combination groups e.g., 2 x sales group + invoice group + a set of customers.