Database Design for Simple Private Messaging - sql-server

The concept is simple:
User click "Send PM" button on one of ads.
Window pop up with "Title" box, "Message" box and send button.
Recipient sees a message with following info: "Sender Name", "Date Received", "Title" and "Message".
Recipient replies by filling: "Title" and "Message" and press reply.
Repeat step 3.
No IP will be stored.
Can you please give me an idea how to make a concise/efficient relational design?

Message table formate
Message
Id
UserID
Message
Send_DateTime
Title
Message_Id ( FK )- self referance
self referance is to keep the track of the whole chat.
for the first message its NULL and than onwards id of relative meesage
Id UserID Message Send_DateTime Title Message_Id ( FK )- self referance
1 1 test datetime tt Null
2 2 test1 datetime tt 1
3 1 test2 datetime tt 2
...
go on

Related

Best way to design Users and Contacts

I have two tables (e.g.):
Users (ID, firstName,middleName, lastName)
Contacts (ID, userID, serialNo, phoneNumber, eMail).
I shall be communicating (sending messages) to Users via phoneNumber or eMail or both and save it in Database (e.g.).
Log (ID, userID, contactID, message, onPhoneOrEmail) where, say, last field stores, say, 'p','e' or 'b', for phoneNumber, eMail, or both.
So, when I check logs, I can get to know that which message was sent to which email/phonenumber.
Problem:
What to do when Users change their contact details?
If I update the Contacts table, I lose Log, because the messages were not sent to the new number.
If I store the number or email in Logs, it would be to much of data to store (on large scale as compared to just one character).
Last: If I add new Contact with +1 serial number (serialNo - field), will it be feasible ? What about performance issues ? (uniqueness is not required, Users can changes number or email as many as times as they want - these are just for communcation).
I read this and this, but could not get an approriate answer regarding performance/methodological issues.
Please guide.
SAMPLE DATA:
USERS
| 1 | John | null | Cena |
CONTACTS
| 1 | 1 | 1 | 123456 | abc#xyz.com
| 2 | 1 | 2 | null | xyz#mnp.com
| 3 | 1 | 3 | 987654 | null
If you say that a User can change his contact detail this means that you inverted the dependency. The User has the Contact, so it is reasonable to associate to a user a contactID and not the opposite. Now, a User can change e.g. phone whenever he wants, and at the same time it make no sense for the same phone number to change its user at some point.
So it would be turned like this:
User(ID, firstName,middleName, lastName, contactID)
Contact(ID,serialNo, phoneNumber, eMail)
Log (ID, userID, message, onPhoneOrEmail).
You don't need both userID and contactID on Log. Remember that one is foreign key for the other (transitive dependency).
EDIT
If you need to store multiple contacts per User, keep your schema but change the Log in
Log (ID, contactID, message, onPhoneOrEmail)
From my point of view, when you need to change contact of a user it means that you will remove one and add another. If you have never sent any message to that contact you are removing, you have no reason to keep it in memory, otherwise, if you need a record you have to maintain the contact information in memory even after you have replaced it (maybe a column saying it is invalid is preferable). This is already the default behavior in mySQL (ON DELETE RESTRICT).
Get rid of your Contact table.
Create a new UserPhone table (PK - ID, FK - User.Id, Phone#, ActiveDate)
Create a new UserEmail table (PK - ID, FK - User.Id, Email,
ActiveDate).
It looks like SerialNumber is just an incrementer for
one User's Contact data. If it is just an incrementer, ActiveDate
should suffice as a replacement.
When phone, email information changes do not update existing record, add new record with today's date instead.
Your Log table will look like (PK - LogID, FK - UserEmail.ID, FK - UserPhone.ID).
No need for the PhoneOrEmail field. That information can be determined by presence of the FKs.
You might have some other design issues but this answer should get you on the right track.

Maintaining two different versions of a record in SQL Server

I have a SQL Server table which has the following columns:
Id, HeaderText, ContentText, ProposedContentId, Active
I want to maintain two versions of records that are edited by users using a website. For example, user John could edit the HeaderText and ContentText fields of the following record and click save.
Id, HeaderText, ContentText, ProposedContentId, Active
==> 1, Hello, This is a test, NULL, 1
But instead of updating that same record I want to create another record and point from the old record to new record. Now the table looks like this:
Id, HeaderText, ContentText, ProposedContentId, Active
1, Hello, This is a test, 2, 0
==> 2, Hello World, This is a new post, NULL, 1
As you can see, the old record is marked as not active and now the ProposedContentId points to the newly created row.
I don't know whether this is good solution to this problem. Please suggest better ways if there are any.
Edit: I only need to maintain two copies (old and new) and I cannot create extra tables.
I personally would not use this Active flag as a way of tracking the latest record. This type of identifier gets tricky to maintain.
I would add a content identifier to your table. Then, when a record gets changed, simply insert the new data with the same content identifier. The Id field will auto increment, or you could add a datetime field, then you can track the active record by looking at record the highest Id (or latest timestamp) for that given ContentId.
Id, ContentId HeaderText ContentText
1 1 Hello This is a test
2 1 Hello World This is a new post
3 1 Hello again! The content was changed again
4 2 New Content This is some new text
5 2 Newer Content This is that other record, updated
You could add in an active flag to this setup if you want, but it doesn't really have to be any more complex than each record having it's own identifier like a ContentId and knowing the active record by whatever has the highest ID, or latest timestamp. However you'd prefer to do it.
If you wanted to get the "active" records, all you'd need to do is run something like this:
SELECT A.*
FROM YourTable A
JOIN (
SELECT ContentId, MAX(Id) MaxId FROM YourTable GROUP BY ContentId) B
ON A.ContentId = B.ContentId AND A.Id = B.MaxId
That should give you the following:
Id, ContentId HeaderText ContentText
3 1 Hello again! The content was changed again
5 2 Newer Content This is that other record, updated
I hope this helps or at least gives you some food for thought.

Postgres - remove element from jsonb array

I have an array of jsonb elements (jsonb[]), with id and text. To remove an element I could use:
UPDATE "Users" SET chats = array_remove(chats, '{"id": 2, "text": "my message"')
But I want to delete the message just by the id, cause getting the message will cost me another query.
Assuming missing information:
Your table has a PK called user_id.
You want to remove all elements with id = 2 across the whole table.
You don't want to touch other rows.
id is unique within each array of chats.
UPDATE "Users" u
SET chats = array_remove(u.chats, d.chat)
FROM (
SELECT user_id, chat
FROM "Users", unnest(chats) chat
WHERE chat->>'id' = '2'
) d
WHERE d.user_id = u.user_id;
The following explanation matches the extent of provided information in the question:

SOQL Salesforce Join and Filter for 3 Different Objects

I would appreciate if someone can help me with the following requirement for building a SOQL.
Object1: Event :
Fields to get: Id, Subject, OwnerId
Object2: EventAttendee :
Fields to get: EventId, AttendeeId
Object3: User :
Fields to get: Id, Email
Note:
Id of Event = EventId of EventAttendee &
AttendeeId of EventAttendee = Id of user
So the requirement is to lookup Id from Event into EventId of EventAttendee and get the respective AttendeeID, then for the same AttendeeId lookup into user to get the Email address.
Thanks for your help.
One way would be to start from Event, go down to Attendees, then up to Users. The table that holds attendees is actually called EventRelation. Something like that should get you started:
SELECT Id, Subject, OwnerId,
(SELECT EventId, RelationId, Relation.Email FROM EventRelations)
FROM Event

Database design for internal Messaging (like facebook message)

In the following database design, how do I mark an unread message, so we know who read the message either the sender and recipient?
(ie When person X sends a message to person Y, the message will be marked as unread for person Y until person Y reads the message, but its marked as read for person X because he sent the message).
MESSAGE
Id (PK)
Subject
Content
MessageTypeId (FK) - Message, Update (global board-cast), notifications etc
UserId (FK) - creator
CreateDate
ReadDate
MESSAGE_COMMENT
Id (PK)
MessageId (FK)
Content
UserId (FK) - creator
CreatedDate
USER
FirstName
LastName
Username
Password
IsActive
etc...etc...
MESSAGE_TYPE
Id
Code
Name
EDIT: it seems like the design is incomplete.
You could add a Read table which links user ID and message ID. When a message is created the application automatically puts in the UserID of the creator and the MessageID. Then when the receiver reads the message it records the ReceiverID and the MessageId.
So while there is no record for ReceiverID and MessageID, the message will appear unread for the receiver.

Resources