Patrik Fuhrmann
Patrik Fuhrmann

Reputation: 977

Database normalization - same fields, different tables

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

Answers (3)

Mohsen Heydari
Mohsen Heydari

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.

enter image description here

Upvotes: 1

Stefan Steiger
Stefan Steiger

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

Javier
Javier

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

Related Questions