I have a table messages for conversations between the users.
The table columns' names are:
messageID | fromUser | forUser | message | submitDate | seen
Sample data:
1 | 1 | 2 | "hi" | "12341" | 0
2 | 2 | 1 | "hi" | "12342" | 0
3 | 1 | 3 | "hi" | "12343" | 0
4 | 1 | 4 | "hi 4" | "12344" | 0
5 | 2 | 1 | "hello" | "12345" | 0
6 | 1 | 2 | "hello how r u?" | "12346" | 0
7 | 3 | 1 | "hello user 1" | "12345" | 0
How I can write a query to find the last message that was sent between myself and every other user in the system? I mean last messages are:
between user 1 and 2 : "hello how r u?"
between user 1 and 3 : "hello user 1"
between user 4 and 1 : "hi 4""
My query:
$query = "SELECT DISTINCT `fromUser`, `forUser`, `message`, `seen`,
`username`, `userPhoto`
FROM `messages`,`user`
WHERE (`forUser`= '$myUserID' OR `fromUser`= '$myUserID')
AND (((`forUser`= `userID`) AND (`forUser` != '$myUserID'))
OR ((`fromUser`= `userID`)
AND (`fromUser` != '$myUserID')))
ORDER BY `submitDate` DESC";
but this query needs to fetch all messages in a conversation! I just need the last message.
Try this simple and easy one it will also find the users of each group Look at my code:-
select m.* ,u.*
from
messages m
inner join (
select max(id) as maxid
from messages
where messages.fromUser = "$myUsreId"
OR messages.forUser = "$myUsreId"
group By (if(fromUser > forUser, fromUser, forUser)),
(if(fromUser > forUser, forUser, fromUser))
) t1 on m.id=t1.maxid
join
users u ON u.id = (CASE WHEN m.fromUser = "$myUsreId"
THEN m.forUser
ELSE m.fromUser
END)
You can use the following query to get the latest message for user with userID = 1 per user conversation with some other user:
SELECT messageID, message, submitDate, otherUser
FROM (
SELECT messageID, message, submitDate,
@row_number:=CASE WHEN @other=otherUser THEN @row_number+1
ELSE 1
END AS row_number,
@other:=otherUser AS otherUser
FROM (
SELECT messageID, message, submitDate,
IF(1 = fromUser, forUser, fromUser) as otherUser
FROM messages AS m
WHERE 1 IN (fromUser,forUser)
ORDER BY otherUser, submitDate DESC) t ) s
WHERE s.row_number = 1
SQL Fiddle Demo
The inner query:
SELECT messageID, message, submitDate,
IF(1 = fromUser, forUser, fromUser) as otherUser
FROM messages AS m
WHERE 1 IN (fromUser,forUser)
ORDER BY otherUser, submitDate DESC
is used to return a list of messages either sent or received by user with userID = 1. Calculated column otherUser simply contains the other user, either sender or receiver, involved in the conversation with user with userID = 1.
In an outer query, variable @row_number is used in order to simulate ROW_NUMBER() OVER (PARTITION BY otherUser ORDER BY submitDate DESC) available in SQL Server.
Finally, the outer query uses the number calculated by @row_number to select only the most recent message per otherUser.
If messageId is an auto_increment primary key then you can use its values to distinguish which is the latest message in each conversation. If submitDate has type DATETIME or TIMESTAMP then would be another choice for that purpose, but if it has type DATE then its resolution is not sufficient.
The key thing, though, is to identify and filter on the timestamps or ids of the latest messages. You can identify the IDs or timestamps on a per-conversation basis with a suitable aggregate (sub)query, and perform the filtering via an inner join, like so:
SELECT m.*
FROM
messages m
JOIN (
SELECT
MAX(messageId),
CASE
WHEN fromUser = '$myUserId' THEN forUser
WHEN forUser = '$myUserId' THEN fromUser
END AS otherUser
FROM messages
GROUP BY
CASE
WHEN fromUser = '$myUserId' THEN forUser
WHEN forUser = '$myUserId' THEN fromUser
END
HAVING otherUser IS NOT NULL
) other
ON m.messageId = other.messageId
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With