how to group reply messages to original message - php

I am storing replies in a separate table with the original message as the reference id. What I'm trying to do is when a message is clicked it grabs all the corresponding replies and displays them under the main message but how to get the corresponding messages?
This is what I've tried but can't find a WHERE clause that works. Is there any way to group these by the to_id and from_id and reference_id or am I on the wrong track all together?
Basic SQL is pretty much my ceiling at this point so any pointer appreciated.
replies table
MESSAGE TABLE
What I want to do is to have one main conversation with someone and if you message them once all further replies and/or new messages appear underneath
EXAMPLE:
MAIN MESSAGE to USER 1
//grouped by date and if a certain period passes block with a line
reply from user 2
reply from user 1
----------------------------
days later
new message from user 2
so on...

Not sure if this is what you are looking for
SELECT m.subject, r.Message, r.from_id, r.to_id FROM MESSAGE m
JOIN replies r on m.reply_id = r.id
WHERE ((m.from_id = `user_1_id` AND m.to_id = `user_2_id`)
OR (m.from_id = `user_2_id` AND m.to_id = `user_1_id`))
ORDER BY r.date_sent asc

Are you looking for something like this? If you can provide the layout of both the messages and replies tables it may help...
SELECT
`messages`.`message`,
`replies`.`reply`
FROM
`messages`
JOIN
`replies` ON(`messages`.`id` = `replies`.`message_id`)

Related

MySQL ORDER BY on a thread-based message system

I've created a message system where users can send messages to each other. It's thread-based like in Facebook. So every user should be in only one specific message-thread with another single user.
The main overview of all messages isn't working as I want it to be. It only shows the oldest (first) message text and date of a thread and doesn't sort by latest message sent.
The MySQL database structure:
messages_assign: id,uid,thread_id,status,date
messages_content: id,uid,thread_id,text,date
messages_thread: id,creator_uid,receiver_uid
I think it's self-explanatory, but to clarify: messages_assign assigns the content(s) to a specific message thread. I want to expand this message system to be able to send messages to multiple users someday, that's why I came up with this structure.
This is my MySQL query in PHP:
$menu = mysql_query("SELECT
t.`id`, t.`creator_uid`,
c.`uid` AS content_uid, c.`text`, c.`date` AS content_date,
a.`status`, a.`date` AS assign_date,
CASE
WHEN t.`creator_uid`='".sInput($_SESSION['uid'])."' THEN `receiver_uid`
WHEN t.`receiver_uid`='".sInput($_SESSION['uid'])."' THEN `creator_uid`
END AS uid
FROM `messages_content` c
LEFT JOIN `messages_thread` t ON t.`id` = c.`thread_id`
LEFT JOIN `messages_assign` a ON a.`id` = t.`id`
WHERE
t.`creator_uid`='".sInput($_SESSION['uid'])."'
OR
t.`receiver_uid`='".sInput($_SESSION['uid'])."'
GROUP BY t.`id`
ORDER BY c.`id` DESC") or die (mysql_error());
I guess that there has to be a sub-query somewhere to let it sort by the latest date and text, but I'm not familiar with that and also wouldn't know where to put that and how?
So basically I just want that the message threads are sorted by the latest message received, showing the latest text and date of a specific thread.

Mysql query with multiple tables and foreign keys

Consider this mysql tables structure (useful to store private/group chat messages):
USERS
user_id
username
password
GROUPS (= DISCUSSIONS / TOPICS)
group_id
name
GROUPS_MEMBERS (= MEMBERS OF A SPECIFIC DISCUSSION / TOPIC)
group_id
user_id
MESSAGES
message_id
timestamp
from_user_id
destination_type (enum - group, user)
destination_id
Can you please help me with the query to retrieve the list of the 5 more recent dicussions (either private or group) in which a specific user has been a active?
Important:
I don't have actual code since I'm just deciding how to structure the database tables. The table structure presented above it's pretty self-explanatory (destination_id is a reference to group_id, and group members are all the users that will receive a message. Finally, all messages sent between the users of a specific group make a discussion or topic).
Here is what I want to do (it's very easy... don't over-think it... it's like any chat/messaging system like Facebook or Gmail etc).
When a user logs in and opens the chat he will of course see all the latest discussion which he is/has been a part of. In a chronological DESC order.
So I need to write the query to retrieve the latest 5 GROUP_IDs (= discussions) in chronological DESC order. But only the discussions which the logged-in user is a part of.(Of course I have the id of the logged-in user.. for example 16)
P.s. I didn't build this table structure myself but it seems logic; the only problem is the one presented above.
Here's my suggestion. You can get different records by using DISTINCT and get only five records by using LIMIT. You can replace logged_in_user_id with the login id.
SELECT DISTINCT GROUPS.group_id FROM USERS
JOIN GROUP_MEMBERS ON USERS.user_id = GROUP_MEMBERS.user_id
JOIN GROUPS ON GROUPS.group_id = GROUP_MEMBERS.group_id
JOIN MESSAGES ON destination_type = 'group' AND destination_id = GROUPS.group_id
WHERE USERS.user_id = logged_in_user_id
ORDER BY timestamp DESC
LIMIT 5;
#Igor Carmagna:
I have gone through your question and according to that i think you are required list the top 5 messages which have been left by the end users right ?. So for that please please follow below given steps.
1) First and for most thing you are required to do is that Join.
2) In this step you are required to use max() function which will give you list of the users on the base of messages received. Now, according to your question you are required to have only top 5 records so you are bound use (max-5) function this will given top 5 records
Hope this will make you day !!
Cheers :) :P

messages between users: show conversations

I am coding a message system for user communication. In the inbox I do not want to show the user the messages he/she received. I just want to show the conversations. So as an example, if one user send or receive more than one message then in the inbox there should only be the conversation (which includes the newest message, either written or received) with the user and when the user clicks on the conversation he/she can see all past messages.
The table structure (simplified) of 'messages' is as followed:
message_id
user_id_sender
user_id_recipient
message
Now the problem is that the messages are saved in a database where each row is one message, so I have to group these messages in a certain way.
The select statement I came up with is the following:
SELECT * FROM messages
WHERE user_id_sender = 1 OR user_id_recipient = 1
GROUP BY user_id_sender
But now I obviously get two messages because one which has been written by user '1' and one that he has received..
Does anybody have an idea how to solve this?
I've solved this problem some month ago. I suppose you have also a date field. This query give you a well structured results with date of last message and last message.
$qry = 'SELECT
CONCAT(GREATEST(user_id_sender,user_id_recipient)," ",LEAST(user_id_sender,user_id_recipient)) AS thread,
MAX(CONCAT(date,"|",message)) as date_message,
MAX(date) AS last_message,
messages.*
FROM messages
WHERE user_id_sender= ? || user_id_recipient=? GROUP BY thread ORDER BY last_message DESC';
$rows = $db->fetchAll($qry, Array($current_user_id,$current_user_id));
Assuming message_id is ascending (i.e. higher ids are for later messages). #user_id is just a placeholder for the user_id of the inbox you are looking at. I've used Andrea's trick for getting the other_recipient_id concisely.
Select
mm.other_recipient_id,
m.*
From (
Select
user_id_sender + user_id_recipient - #user_id as other_recipient_id,
Max(message_id) as message_id
From
messages
Where
user_id_sender = #user_id Or
user_id_recipient = #user_id
Group By
user_id_sender + user_id_recipient - #user_id
) mm
Inner Join
messages m
On
mm.message_id = m.message_id
Example fiddle http://sqlfiddle.com/#!2/05d191/3/0
You get only one message, as long as the messages (message_id) are unique. You will get multiple messages, of course, if there is a longer communication going on.
N.B.: You don't need group by here, because this is used only for aggregating columns, e.g.:
SELECT user_id_sender, sum(*) FROM messages
GROUP BY user_id_sender;
where you get the sum of messages each user has sent.
So, if you want to see the communication between two users:
SELECT * FROM messages
WHERE user_id_sender = 1 OR user_id_recipient = 1;
You can restrict this further, if you store the timestamps as well, message_time for example or limit the number of messages displayed:
select * from ... limit 10;
Assuming we want to see conversations of user with certain _ ID _, this query can be useful:
SELECT (user_id_sender + user_id_recipient) - _ID_ AS correspondent, COUNT(*) AS total
FROM messages
WHERE user_id_sender = _ID_ OR user_id_recipient = _ID_
GROUP BY (user_id_sender + user_id_recipient)
The resulting query returns the ID of the other user of the conversation ("correspondent") and the number of messages between the two users ("total").
Regards

SQL for displaying and sorting messages and their replies in one table

I have written a simple messaging system for a CMS I am developing and am having a hard time finding the best way to grab all the messages and their replies ordered by the newest (message or reply).
I have a table called "messages" that has the fields:
*id, active[1,0], subject, message, datetime, user_from, user_to, reply_id*
It's all straight forward and the *reply_id* is empty for main level messages and contains the parent id for replies. I am at a loss for how to write the SQL to grab all the main level messages in datetime DESC order based on themselves AND their replies. I'm sure it's done with a UNION of some sort but my SQL skills are lacking. And if the same SELECT can give a count of the replies within each main level message that would be amazing!
Any help would be greatly appreciated!
It's late and I'm tired but I think you could try something like that:
SELECT main.*, COUNT(reply.id) AS cnt_replies, MAX(reply.datetime) AS max_datetime
FROM posts AS main
LEFT JOIN posts AS reply
ON main.id = reply.reply_id
GROUP BY main.id
HAVING main.reply_id IS NULL
ORDER BY max_datetime DESC
EDIT: fixed query
EDIT2: now includes messages without any replies

Grouping Records with the same value

I am trying to create a conversations based messaging system.
I want to group all messages that have the same conversation_id so that when I display a list of current conversations you only see the latest message from each conversation.
Can I group the values in the mysql query, or would I have to do it in the php?
select m.convos_id, m.message_content from messages m
where m.id in
(select MAX(m1.id) from messages m1 GROUP BY m1.convos_id)
Thanks for your help, this is what I have ended with.
SELECT messages.*, messages_conversations.subject
FROM messages, messages_conversations
WHERE messages.to_user_id = '".$userid."'
AND messages_conversations.id = messages.conversation_id
GROUP BY messages.conversation_id
You can group that in mysql query something like t this:
select * from table where conversation_id = id_here
This will get all the records that have conversation_id set to id_here and then you can use php to work on that array/group.
Its a basic example of parent child relation in database.
each message much have unique id and iys should also refer to the parent key of convo id.
then you can get the latest message for a given convo id.

Categories