private message database design - database

I'm creating a simple private message system and I'm no sure which database design is better.
The first design is a table for messages, and a table for message comments:
Message
---------------
id
recipientId
senderId
title
body
created_at
MessageComment
---------------
id
messageId
senderId
body
created_at
the second design, is one table for both messages and comments, and an addition field messageId so i'll be able to chain messages as comments.
Message
---------------
id
recipientId
senderId
messageId
title
body
created_at
I'd like to hear your opinion!

In this case, I'd vote for one table.
In general, whenever the data in two tables is the same or very similar and the logical concepts they represent are closely related, I'd put them in a single table. If there are lots of differences in the data or the concepts are really different, I'd make them two tables.
If you make two tables and you find yourself regularly writing queries that do a union of the two, that's an indication that they should be combined.
If you make one table but you find there are many fields that are always null for case A and other fields that are always null for case B, or if you're giving awkward double-meanings to fields, like "for type A this field is the zip code but for type B it's the product serial number", that's an indication they should be broken out.

Using a single table is the most advantageous.
It allows better message threading possibilities and it reduces duplication of effort, i.e. what happens when you want to add a column.

I would rather use the first one and include an additional field del_code to both tables. So, you'll be able to hide deleted messages and still have them in your database.

Related

Data Modeling: Is it bad practice to store IDs from various sources in the same column?

I am attempting to merge data from various sources into an existing data model. Each source uses different types of IDs (such as GUID, Salesforce IDs, etc.). For example, if I were to merge data from two different sources, the table may look like the following (where the first two SalesPersonIDs are GUID IDs and the second two are Salesforce IDs):
Is this a bad practice? I could also imagine a table where each ID type was its own column and could be left blank if it was not applicable. Something like the following:
I apologize, I am a bit new to this. Thanks in advance for any insight, I greatly appreciate it!
The big roles of an ID column are to act as a key connecting data in different tables, and to help indexing - quickly find rows so your queries run fast.
The second solution wouldn't work well for these purposes, and will lead to big headaches in queries: every time you want to group by the ID, you'll have to combine the info from 2 columns in some way, hopefully getting a correct unique result every time.
On the one hand, all you might ever need from an ID is for it to be unique. The first solution might be fine this respect - but are you sure you'll never, ever get data about one SalesPerson from more than one source?
I'd suggest keeping all the IDs in one column, and adding a column to say what kind of ID this is. At least this way, you won't lose any information and can do other things in the future.
One thing you might consider is making a separate table of SalesPerson with all their possible IDs, and have this keyed to other (Sales?) data by a unique ID used only in your database.

Suggestions for chat system schema design

I need a suggestion about sql table schema. I've opened a table and named it Chats, would it be better for me to add two columns(like ID and Messages) or one that will contain the IDs and the messages? And which one of them will work faster
Personally I'd model this as two tables:
Chats
- ID
- Name
Messages
- ID
- ChatID
- Message
- SentDate
There should be a foreign key from Messages.ChatID to Chats.ID.
Otherwise you're going to have to create duplicate chats each time someone sends a message.
I would strongly recommend against keeping IDs and Values in the same column, it makes it near impossible to join on and will create all sorts of problems later on.
There is no reason to use a single column. Add as many columns as possible, each with its own data type because you will be able to filter and sort the table by each column later. You will also be able to add constraints, indexes, statistics, etc... if needed.
Any query performed on that table will work faster if you use separate columns.

Getting records structured the same way only partially

While surfing through 9gag.com, an idea (problem) came up to my mind. Let's say that I want to create a website where users can add diffirent kinds of entries. Now each entry is diffirent type and needs diffirent / additional columns.
Let's say that we can add:
a youtube video
a cite which requires the cite's author name and last name
a flash game which requires additional game category, description, genre etc.
an image which requires the link
Now all the above are all entries and have some columns in common (like id, add_date, adding_user_id, etc...) and some diffirent / additional (for example: only flash game needs description or only image needs plus_18 column to be specified). The question is how should I organize DB / code for controlling all of the above as entries together? I might want to order them, or search entries by add_date etc...
The ideas that came up to my mind:
Add a "type" column which specifies what entry it is and add all the possible columns where NULL is allowed for not related to this particular type columns. But this is mega nasty. There is no data integration.
Add some column with serialized data for the additional data but it makes any filtration a total hell.
Create a master (parent) table for an entry and separate tables for concrete entry types (their additional columns / info). But here I don't even know how I'm supposed to select data properly and is just nasty as well.
So what's the best way to solve this problem?
The parent table seems like the best option.
// This is the parent table
Entry
ID PK
Common fields
Video
ID PK
EntryID FK
Unique fields
Game
ID PK
EntryID FK
Unique fields
...
What the queries will look like will largely depend on the type of query. To, for example, get all games ordered by a certain date, the query will look something like:
SELECT *
FROM Game
JOIN Entry ON Game.EntryID = Entry.ID
ORDER BY Entry.AddDate
To get all content ordered by date, will be somewhat messy. For example:
SELECT *
FROM Entry
LEFT JOIN Game ON Game.EntryID = Entry.ID
LEFT JOIN Video ON Video.EntryID = Entry.ID
...
ORDER BY Entry.AddDate
If you want to run queries like the one above, I suggest you give unique names to your primary key fields (i.e. VideoID and GameID) so you can easily identify which type of entry you're dealing with (by checking GameID IS NOT NULL for example).
Or you could add a Type field in Entry.

Table design with joining tables or separate ID in main table

I'm designing a database that has a couple of tables; FAQ's, Bulletins, and Attachments. Bulletins and FAQ's could have an attachment associated with them, so my initial thought was to create a joining table with the two primary keys as a composite key:
Bulletin
--------
BulletinID
Subject
Description
Notes
Attachment
-----------
AttachmentID
FileName
FilePath
etc.
Joining table:
BulletinAttachments
-------------------
BulletinID
AttachmentID
As I design this, I also thought, what if other entities are introduced later (say Newsletter, Email, etc.) that need Attachments as well. I would have to create a joining table for each of these entities. Not awful, but it made me think, what if I got rid of the joining tables and put an AttachmentType in the Attachment table and then assigned the type accordingly:
AttachmentType
--------------
AttachmentTypeID
AttachmentType
Description
The data in that table would be:
1-Bulletin
2-FAQ
3-Newsletter
4-Email
Then the Attachment table would hold the AttachmentTypeID to identify it:
Attachments
-----------
AttachmentID
AttachmentTypeID
FileName
FilePath
etc.
So my question is, for performance wise (using SQL 2008 R2), is there a better choice between the two? Is there a better way to design this? My concern with using individual joining tables is that we may have more entities come along and to accommodate Attachments, we would have to create a joining table and on our front-end software, we would have to write logic for it whereas the AttachmentTypeID would allow the front-end to insert a new AttachmentType and no db interaction would be needed.
Your second solution doesn't have a way to link the attachment to the item, just what kind of item it is.
Even if it did (ie: an itemID), what you would create would be a violation of 4th Normal form - ie: a multivalued dependency.
Stick with your first plan, but consider whether Bulletins are fundamentally different to Newsletters, Emails, FAQs, etc in your application. If you do need a new table for Newsletters, add a new table for NewsletterAttachments.
Also consider, are you going to share attachments between different items, or types of item?
I am totally agree with podiluska. you need to create separate table for each type of attachment otherwise you cant map itemid with attachment and you will face a problem of joining table for different type of attachment . also if you make separate table for each type of attachment then performance will be faster .

should i consolidate these database tables .

i have an event calendar application with a sql database behind it and right now i have 3 tables to represent the events:
Table 1: Holiday
Columns: ID, Date, Name, Location, CalendarID
Table 2: Vacation
Columns: Id, Date, Name, PersonId, WorkflowStatus
Table 3: Event
Columns: Id, Date, Name, CalendarID
So i have "generic events" which go into the event tableand special events like holidays and vacation that go into these separate tables. I am debating consolidating these into a single table and just having columns like location and personid blank for the generic events.
Table 1: Event:
Columns : Id, Date, Name, Location, PersonId, WorkflowStatus
does anyone see any strong positives or negative to each option. Obviously there will be records that have columns that dont necessarily apply but it there is overlap with these three tables.
Either way you construct it, the application will have to cope with variant types. In such a situation I recommend that you use a single representation in the DBM because the alternative is to require a multiplicity of queries.
So it becomes a question of where you stick the complexity and even in a huge organization, it's really hard to generate enough events to worry about DBMS optimization. Application code is more flexible than hardwired schemata. This is a matter of preference.
If it were my decision, i'd condense them into one table. I'd add a column called "EventType" and update that as you import the data into the new table to specify the type of event.
That way, you only need to index one table instead of three (if you feel indexes are required), the data is all in one table, and the queries to get the data out would be a little more concise because you wouldn't need to union all three tables together to see what one person has done. I don't see any downside to having it all in one table (although there will probably be one that someone will bring up that i haven't thought of).
How about sub-typing special events to an Event supertype? This way it is easy to later add any new special events.
Data integrity is the biggest downside of putting them in one table. Since these all appear to be fields that would be required, you lose the ability to require them all by default and would have to write a trigger to make sure that data integrity was maintained properly (Yes, this must be maintained in the database and not, as some people believe, by the application. Unless of course you want to have data integrity problems.)
Another issue is that these are the events you need now and there may be more and more specialized events in the future and possibly breaking code for one type of event because you added another specialized field that only applies to something else is a big risk. When you make a change to add some required vacation information, will you be sure to check that it doesn't break the application concerning holidays? Or worse not error out but show information you didn't want? Are you going to look at the actual screen everytime? Unit testing just of code may not pick up this type of thing especially if someone was foolish enough to use select * or fail to specify columns in an insert. And frankly not every organization actually has a really thorough automated test process in place (it could be less risk if you do).
I personally would tend to go with Damir Sudarevic's solution. An event table for all the common fields (making it easy to at least get a list of all events) and specialized tables for the fields not held in common, making is simpler to write code that affects only one event and allowing the database to maintain its integrity.
Keep them in 3 separate tables and do a UNION ALL in a view if you need to merge the data into one resultset for consumption. How you store the data on disk need not be identical to how you need to consume the data so long as the performance is adequate.
As you have it now there are no columns that do not apply for any of the presented entities. If you were to merge the 3 tables into one you'd have to add a field at the very least to know which columns to expect to be populated and reduce your performance. Now when you query for a holiday alone you go to a subset of the data that you would have to sift through / index to get at the same data in a merged storage table.
If you did not already have these tables defined you could consider creating one table with the following signature...
create table EventBase (
Id int PRIMARY KEY,
Date date,
Name varchar(50)
)
...and, say, the holiday table with the following signature.
create table holiday (
Id int PRIMARY KEY,
EventId int,
Location varchar(50),
CalendarId int
)
...and join the two when you needed to do so. Choosing between this and the 3 separate tables you already have depends on how you plan on using the tables and volume but I would definitely not throw all into a single table as is and make things less clear to someone looking at the table definition with no other initiation.
Or combine the common fields and separate out the unique ones:
Table 1: EventCommon
Columns: EventCommonID, Date, Name
Table 2: EventOrHoliday
Columns: EventCommonID, CalendarID, isHoliday
Table3: Vacation
Columns: EventCommonID, PersonId, WorkflowStatus
with 1->many relationships between EventCommon and the other 2.

Resources