Reputation: 977
Suppose I have 2 tables. Campaigns and Advertisers. Each of these table has some of the fields exactly same as follows (these is not complete list of fields, I am showing only ones that are same):
Edit: As asked in the comments I will explain more closely relationships. Each advertiser has 0 to many campaigns. 1 campaign belongs to exactly 1 advertiser. There is another table, let's call it "Offer". When new offer is created, all of the counts columns needs to be increased (campaigns.monthly_count, campaigns.total_count, advertisers.monthly_count, advertisers.total_count). Limits columns are specific caps which the counts columns cannot exceed.
campaigns
monthly_limit (int)
total_limit (int)
monthly_count (int)
total_count (int)
advertisers
monthly_limit (int)
total_limit (int)
monthly_count (int)
total_count (int)
Question is: Is it normalized database design or is there better way to do things?
I was thinking about having another table like this:
limits
campaign_id (int)
advertiser_id (int)
monthly_limit (int)
total_limit (int)
monthly_count (int)
total_count (int)
But this way one of the referenced columns would be always empty and I cannot use foreign keys.
Or another option probably is something like this:
limits_campaigns
campaign_id (int)
monthly_limit (int)
total_limit (int)
monthly_count (int)
total_count (int)
limits_advertisers
advertiser_id (int)
monthly_limit (int)
total_limit (int)
monthly_count (int)
total_count (int)
This way I would have to write probably lot more joins in the queries but I could use foreign keys.
Is there any other option which seems more appropriate and if not which of these designs is the best?
P.S.: Just to be more specific I am using MySQL InnoDB engine.
Upvotes: 0
Views: 1635
Reputation: 7284
There will be another approach:
Having a base table called limitable-entity
(my naming is not satisfying) with one-to-on relation to campaign and advertiser.
limitable-entity will be the implementation of generalization pattern in database design.
Upvotes: 1
Reputation: 82136
As you have found out yourself, doing it this way:
campaign_id (int)
advertiser_id (int)
monthly_limit (int)
total_limit (int)
monthly_count (int)
total_count (int)
You have two primary keys. That's not possible even when you just use campaign_id as primary key, because of the not null and/or unique constraint of a primary key.
What you can use is a composite primary key:
item_id (int)
item_type (int)
monthly_limit (int)
total_limit (int)
monthly_count (int)
total_count (int)
primary key(item_id, item_type)
Then you can have a reference table Ref_Item_Type:
1 campaign
2 advertiser
3 whatever
N ...
Then you can reference the composite primary key as foreign key, and you won't have to do any join / union if you want to get all items.
CREATE TABLE SecondaryTable (
AutoID int,
Key1 int,
Key2 int
)
ALTER TABLE SecondaryTable
ADD CONSTRAINT FK_Whatever FOREIGN KEY (Key1, Key2) REFERENCES PrimaryTable (item_id, item_type)
Upvotes: 0
Reputation: 2159
Based on your comments:
Table advertisers:
advertiser_id PK
monthly_limit (int)
total_limit (int)
monthly_count (int)
total_count (int)
Table campaigns, with reference to the advertiser in which it belongs
campaign_id PK
advertiser_id FK
monthly_limit (int)
total_limit (int)
monthly_count (int)
total_count (int)
About the counts, you should control that with your business logic.
Upvotes: 0