Get MAX results of pm messages - php

I'm trying to get the last result of each conversation between two users with no prevail. I've looked at a few examples online such as
[php Mysql Grouping and Ordering user messages together
AND a more advanced query
[GROUP BY messages MySQL
My database structure below.
My conversations rely on getting id's of both message_creator and message_target to link them into one chat.
message_id,
message_content,
message_target,
message_creator,
message_status,
message_time
I need message_status to also select 1 AND 2 in the query so if a user has read the last message it still shows as last message in the conversation.
Here is the query I currently have.
$callmessage=" SELECT message_id,MAX(message_content) AS message_content ,message_target,message_status,message_creator,message_throughurl,MAX(message_time) AS message_time FROM messages WHERE message_target='$user1_id' OR message_creator='$user1_id' AND message_status=1 OR message_status=2
Group By
(if(message_creator > message_target, message_creator,message_target))
,(if(message_creator > message_target, message_target,message_creator))
ORDER BY message_id DESC";

If you want to get the very last message between two users, then this should work:
SELECT *
FROM messages
WHERE (
(message_creator='$user1_id' AND message_target='$user2_id')
OR
(message_creator='$user2_id' AND message_target='$user1_id')
)
AND message_status IN (1,2)
ORDER BY message_id DESC
LIMIT 1

Ok. I've worked it out and its working. This is what I've done with my query, just a few little bits to add.
$user1_id= mysqli_real_escape_string($mysqli,$_SESSION['id']);
$callmessage=" SELECT * FROM messages WHERE message_id IN
(SELECT MAX(message_id) AS message_id FROM
(SELECT message_id, message_creator AS id_with
FROM messages
WHERE message_target = '$user1_id'
UNION ALL
SELECT message_id, message_target AS id_with
FROM messages
WHERE message_creator= '$user1_id') t
GROUP BY id_with)";

Related

Query Join 2 tables based on specific conditions

I have 2 MYSQL tables.
My 2 tables in a simple way
The first table, stores the conversations, second table stores the messages related to conversation in the first table, I need to write a query to view each conversation from the first table and only the last received message (order by msg_time) from the second table.
I have tried this, it works but gives the oldest message from second table:
$query = "SELECT * FROM tbl_conversations inner JOIN
tbl_messages ON tbl_messages.convers_id = tbl_conversations.id
GROUP BY id ORDER BY tbl_messages.msg_time DESC";
And also I need to display the conversation that has the most recent message on top, I mean to display the conversations according to the time of their last messages. Thanks for your support.
I think you get ambiguous error
because id in group by must be write like this tbl_conversations.id
$query = "SELECT * FROM tbl_conversations inner JOIN
tbl_messages ON tbl_messages.convers_id = tbl_conversations.id
GROUP BY tbl_conversations.id ORDER BY tbl_messages.msg_time DESC";

Group by avoids order by

I'm trying to list the messages by a loop as primarily last messages in PDO,
but I have a group by command too in the sql and it doesn't work as well.
I'm using group by for avoid the multiple messages in a page from same user.
So the user should see the messages as DESC but group by is avoiding ranking.
messages should be listed as (example):
conversation 1: last message - from
conversation 2: last message - from
conversation 3: last message - from
every conversation should contains unique sender name and the conversations that has new messages should be at top (DESC)
my sql code:
SELECT *
FROM pm
WHERE pm_to={$session['id']}
GROUP BY pm_from
ORDER BY id DESC
The pm_table structure are:
id - int(11) auto_increment
pm_from - int(11)
pm_to - int(11)
pm_content - text
For selecting the last message from each user to a gived user ($session['id']), you need to:
Get the list of the latest id of each conversation
Get the complete message list
I've wrote a SQL query who should do it.
SELECT pm.*
FROM pm
JOIN (SELECT MAX(id) AS id_pm
FROM pm
WHERE pm_to={$session['id']}
GROUP BY pm_from) DT1
ON DT1.id_pm = pm.id
ORDER BY id DESC

PHP MYSQL - Distinct multiple columns as one

I've read a lot of questions and answers related to this topic, but I can't find anything that's working for me, so I could really use some help.
I am trying to make a simple private messaging system for my website. I have a table like this:
private messages: id, to_id, from_id, message, time_sent
I am now trying to show a list on my page with the different users a member interacted with, something like Facebook messages so every name should appear only once in the list.
This is what I have now which shows me every message that I as a user ($my_id) participate in:
SELECT * FROM private_messages WHERE (from_id = '$Sid' AND to_id = '$my_id') OR (from_id = '$my_id' AND to_id = '$Sid') ORDER BY time_sent ASC
This query shows a distincted list, but only of the people that I received a message from:
SELECT DISTINCT(from_id) FROM private_messages WHERE to_id='$my_id' ORDER BY time_sent DESC
How should I rewrite this so it gives me a distinct list of every user that I interacted with (like a list of facebook messages)? I think I need to distinct on two columns, from_id and to_id, but how should I do it?
I know the questions sounds rather vague, but I really can't explain it any better. Thanks in advance!
Try this:
SELECT DISTINCT IF(from_id = '$my_id', to_id, from_id) AS other_id
FROM private_messages
WHERE '$my_id' IN (to_id, from_id)
ORDER BY time_sent DESC

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

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