1

Trying to recreate a private message system similar to what Facebooks setup these days. The part im having a problem with is SELECT only newest message from distinct threads order by timestamp.

Here is the closest query I could come up with so far. The problem is the inbox should only return one row for each thread and currently my query returns multiple rows from the same thread:

SELECT m.created_on, m.thread_id, m.message_id, m.created_by, m.body, u.first_name, u.last_name, u.thumb_img

FROM pms_messages AS m, pms_recips AS r, users AS u

WHERE r.uid =19

AND r.status

IN ('A', 'N'
)

AND r.thread_id = m.thread_id

AND (SELECT max(r.message_id)) = m.message_id 

AND m.created_by = u.uid

ORDER BY created_on DESC

Here is a img of my current db setup , im open to changes to my tables if it would simplify my querys and get the job done. Further down is more detailed explanation of my tables/the inbox specs.

enter image description here

To be more specific:

*Messages between any two users occurs on a single , ongoing thread. All messages between any 2 users is just a continuation of one ongoing conversation(thread) Even if both users delete all previous messages between each other any future messages will still occur on the same thread.

*individual messages are tracked by message_id.

*Each thread is only displayed once in the inbox at any given time and will display the most recent msg from the the thread.

*Instead of a inbox and a outbox messages being received and sent will be displayed in the same inbox.

So if im User A and I have a message I havent read yet from user B-20 minutes ago, I responded to a msg user C sent me yesterday- 10 minutes ago and another message from user D - 2 minutes ago my inbox should look like this:

Thread with USER D - displaying msg user D sent me.


Thread with USER C- - displaying msg I sent to user C


Thread with USER B - displaying msg user B sent me


*the threads being displayed will be sorted by most recent - to oldest .

ChuckKelly
  • 1,742
  • 5
  • 25
  • 54

2 Answers2

1

JOIN with the table pms_messages with the following:

SELECT thread_id, MAX(Created_ON) AS NewestDate
FROM messages 
GROUP BY thread_id

Then it will remove all the messages but the latest one that has MAX(Created_ON). Like this:

SELECT 
  m.created_on, 
  m.thread_id, 
  m.message_id, 
  m.created_by, 
  m.body, 
  u.first_name, 
  u.last_name, 
  u.thumb_img
FROM pms_messages AS m
INNER JOIN
(
   SELECT thread_id, MAX(Created_ON) AS NewestDate
   FROM messages 
   GROUP BY thread_id
) AS m2  ON m.created_on = m2.Newestdate
        AND m.thread_id  = m2.thread_id
INNER JOIN pms_recips AS r ON r.thread_id  = m.thread_id
INNER JOIN users      AS u ON m.created_by = u.uid
WHERE r.uid =19
  AND r.status IN ('A', 'N')
ORDER BY created_on DESC;

Update 1

Add r.message_id = m.message_id to the JOIN condition between the two tables pms_messages, pms_recips. Like this:

SELECT 
  m.created_on, 
  m.thread_id, 
  m.message_id, 
  m.created_by, 
  m.body, 
  u.first_name, 
  u.last_name, 
  u.thumb_img
FROM pms_messages AS m
INNER JOIN
(
   SELECT thread_id, MAX(Created_ON) AS NewestDate
   FROM pms_messages
   GROUP BY thread_id
) AS m2  ON m.created_on = m2.Newestdate
        AND m.thread_id  = m2.thread_id
INNER JOIN pms_recips AS r  ON r.thread_id  = m.thread_id 
                           AND r.message_id = m.message_id
INNER JOIN users      AS u  ON m.created_by = u.uid
WHERE r.uid =19
  AND r.status IN ('A', 'N')
ORDER BY created_on DESC;

SQL Fiddle Demo

Mahmoud Gamal
  • 78,257
  • 17
  • 139
  • 164
  • idk if this has anything to do with the problem , but i probably should of mentioned that 2 records are saved in the pms_recips table every time a new message is added. 1 for the user its being sent to and 1 for the user that sent it. – ChuckKelly Feb 24 '13 at 06:50
  • Ive tried using distinct on the query i originally posted, but it told me invalid use of GROUP BY. Just to be honest im only intermediate at best when it comes to mysql. Im trying to do research now, but I havent the slightest clue how to modify the query you gave me to use distinct. – ChuckKelly Feb 24 '13 at 06:53
  • @ChuckKelly Can you please post some sample data of the three tables and the desired output, just a sample records from each. And if possible try to setup a demo in [**this site**](http://www.sqlfiddle.com/) this will be very helpful. Thanks. – Mahmoud Gamal Feb 24 '13 at 06:54
  • @ChuckKelly - Sorry I am on work right now. But, what is the problem? Try to edit your question and explain any further issues do you have in the query. – Mahmoud Gamal Feb 24 '13 at 07:41
  • I tried my best to insert my data into MysqlFiddle , let me know if i did it wrong and i will do my best to format it properly for you. – ChuckKelly Feb 24 '13 at 07:41
  • Any given pair of 2 users has 1 and only 1 on going thread that holds ongoing conversation between the 2 users. Just as when you view your inbox on fb , any thread between you and another user should only have one single row when viewed from the inbox. so even if a user sends me 200 messages - when viewed from the inbox that thread will only be displayed once and it should display only the most recent of the 200 messages. Currently the query you gave me returns the newest messages on a thread , but it displays as many duplicates as there are individual messages on that given thread of that msg – ChuckKelly Feb 24 '13 at 07:50
  • Nvm , did not see the updated post!!! thank you much sir, sorry if i was a bother!! – ChuckKelly Feb 24 '13 at 07:54
  • @ChuckKelly Its al right, you are welcome any time :) Feel free to bother me and other users here with your questions any time :) That is why we love Stackoverflow, to help others and learn from them. Good luck. – Mahmoud Gamal Feb 24 '13 at 08:25
  • I saw you're profile , are you available for hire? You seem to know you're way around Mysql and we could use someone to oversee/advise on our backend. idk if it appropriate for me to ask about this here, but if you're interested email me at fresh83 at live dot com – ChuckKelly Feb 24 '13 at 12:18
  • @ChuckKelly - Yes, I am available for hire, and ready any time. OK, I will email you ASAP. – Mahmoud Gamal Feb 24 '13 at 14:27
0
    SELECT * FROM 
        (SELECT * FROM messages ORDER BY created_at DESC) messages
    GROUP BY IF(from_user_id < to_user_id, CONCAT_WS('_', from_user_id, to_user_id), CONCAT_WS('_', to_user_id, from_user_id));
damlys
  • 106
  • 1
  • 8