Postgresql – Database Design – One table from many source(One to One)

database-designpostgresql

I have a 'Text' table, the text table may came from different source, like Tweet, SMS, Email, etc. and each source have their own log, and Text is came from the source. so i came with some solution, but i don't know which is the best.

Solution 1 :

Text(
text_id PK
content
source_type (tweet, sms, email, etc)
source_id (can't be FK since it may contain sms_id, tweet_id, or email_id)
)

Tweet(
tweet_id PK
tweet_text
tweet_username
etc...
)

Sms(
sms_id PK
sms_text
sender_number
etc...
)

Email(
email_id PK
email_text
email_sender
etc...
)

Solution 2 :

Text(
text_id PK
content
sms_id FK
tweet_id FK
email_id FK
)

Tweet(
tweet_id PK
tweet_text
tweet_username
etc...
)

Sms(
sms_id PK
sms_text
sender_number
etc...
)

Email(
email_id PK
email_text
email_sender
etc...
)

Please note that one 'Text' only came from one source.

so if I use solution 2, let say the source is came from sms then the data will look like this

Text(
12
'the text'
333
null
null
)

Sms(
333
'the text'
0818833733664
etc...
)

so which is the best approach ?

UPDATE :
I miss a big part on my question, and that's are may fault, sorry for that. In my case the Text also may came from a csv(excell) file. which mean one file may have many text, because the file is a dump for many text(coma or row separated). SMS, Tweet, and Email relation with Text is one to one, but File with Text is One to Many
so the big missing part in my question is the File Table

File(
file_id PK
file_name
etc..
)

Best Answer

I do not like both of your solutions.

  • Solution 1: Storing different things at the same place is a bad idea. Storing foreign key to different tables in the same field is worse.
  • Solution 2: this is also no a good idea. You get a lot of NULL values. The best thing is to draw a picture.

My prefered solution is that of @Joel Brown (with some minor changes) Instead of 'text' i woul call the supertype 'message' and it should not only hold the content but the all fields (and references) common to all message types.

subtype.png

message(
  message_id PK
  content
  common attributes ...
)

Tweet(
  message_id PK, FK
  tweet_username
  tweet attributes
)

Sms(
  message_id PK, FK
  sender_number
  sms attributes ...
)

Email(
  message_id PK, FK
  email_sender
  email attributes ...
)

The implementation is straight forward: each entity is a table. the superentity has a primary key. this primary key is used for the subentities too. If you want model your system with an entity text that has relationships to entities sms, email and tweet as described in your post, you get the following EER diagram

relsationship.png

I don't like this model in your special case but there are other situation where such a model is appropriate.

There is a standard way to transform such 1:1-entities to tables. we have three relations sends, mails, tweets which have an optional entity (SMS,Email,Tweet) and a mandatory Entity (Text). In this case the foreign key is stored in the table of the optional entity. (You did it the wrong way) So you get the following tables

text(
  text_id PK
  content
  other attributes ...
)

Tweet(
  tweet_id PK
  text_id FK
  tweet_username
  tweet attributes
)

Sms(
  sms_id PK
  text_id FK
  sender_number
  sms attributes ...
)

Email(
  email_id PK
  text_id FK
  email_sender
  email attributes ...
)

Using Extended Entity Relationship Diagrams (and maybe any other modelling method) makes it almost impossible to create without cheating such solutions that you have proposed. Diagrams can be drawn with pencil and paper. The diagrams in this post are created with DIA. The Extended Entity Relationship Model and how to transfer it into tables can be found in T.J.Teorey, D.Yang,J.P.Fry: A Logical Design Methodology for Relational Databases Using the Extended Entity-Relationship Model