Reputation: 6805
I currently have the following tables for a private messaging forum:
alt text http://img159.imageshack.us/img159/45/pmdata.jpg
alt text http://img504.yfrog.com/img504/3968/pminfo.jpg
What I'm trying to do is output an "inbox" that displays the most recent thread at the top and group by thread (meaning, you don't see the same thread twice in your inbox), no matter who the sender is.
What I have right now works fine for simple messages between 2 uesrs. However, once a third user replies to the same thread, it doesn't display correctly. My current query is this:
SELECT pm_info.is_read, sender.usrFirst as sender_name, pm_data.date_sent, pm_data.title, pm_data.thread_id, pm_data.id as dataid, thread_max_date_sent
FROM pm_info
INNER JOIN pm_data ON pm_info.message_id = pm_data.id
INNER JOIN tblUsers AS sender ON pm_data.sender_id = sender.usrID
INNER JOIN (SELECT thread_id, sender_id, MAX(date_sent) AS thread_max_date_sent FROM pm_data GROUP BY thread_id, sender_id) deriv1 ON pm_data.thread_id = deriv1.thread_id AND pm_data.date_sent = deriv1.thread_max_date_sent AND pm_data.sender_id = deriv1.sender_id
WHERE pm_info.receiver_id = '$usrID'
ORDER BY deriv1.thread_max_date_sent DESC
Assuming that $usrID = 68 (hence, receiver_id = 68), it outputs this:
From: Kyle (pm_data.id = 18) RE: single message (thread_id= 13587)
From: Ed (pm_data.id = 12) RE: single message (thread_id= 13587)
From: Ed (pm_data.id = 8) RE: Test Number 2 (thread_id= 16256)
Notice how the thread_id (13587) shows up twice because there are 2 different senders.
How could I have it just display the most recent thread_id, no matter who the sender is?
Many thanks!!
Upvotes: 3
Views: 418
Reputation: 72510
My suggestion would be to split your database into two tables for better normalization: "thread" and "message". There is thread information that would be common to all messages, like the thread title. You're wasting space in the message table by repeating the same values.
You can have a "last post time" field the the thread table, which is updated on each new post. Then it's only a simple matter of selecting from the thread table and ordering by the last post. It will be a lot faster too.
Upvotes: 0
Reputation: 1437
It actually seems like the query in the original question only requires a very small change for getting the actual most recent record for each thread.
SELECT pm_info.is_read, sender.usrFirst as sender_name, pm_data.date_sent, pm_data.title, pm_data.thread_id, pm_data.id as dataid, thread_max_date_sent FROM pm_info INNER JOIN pm_data ON pm_info.message_id = pm_data.id INNER JOIN tblUsers AS sender ON pm_data.sender_id = sender.usrID INNER JOIN (SELECT thread_id, /*sender_id,*/ MAX(date_sent) AS thread_max_date_sent FROM pm_data GROUP BY thread_id /*, sender_id*/) deriv1 ON pm_data.thread_id = deriv1.thread_id AND pm_data.date_sent = deriv1.thread_max_date_sent /*AND pm_data.sender_id = deriv1.sender_id*/ WHERE pm_info.receiver_id = '$usrID' ORDER BY deriv1.thread_max_date_sent DESC
As a side note: if possible, look for the max messageID in that subquery instead of max(date_sent)
Upvotes: 0
Reputation: 8406
Try
SELECT pm_info.is_read, group_concat(DISTINCT sender.usrFirst) as sender_name,
pm_data.date_sent, pm_data.title, pm_data.thread_id, pm_data.id as dataid,
MAX(date_sent) AS thread_max_date_sent
FROM pm_info
INNER JOIN pm_data ON pm_info.message_id = pm_data.id
INNER JOIN tblUsers AS sender ON pm_data.sender_id = sender.usrID
WHERE pm_info.receiver_id = '$usrID'
GROUP BY pm_data.thread_id
ORDER BY thread_max_date_sent DESC;
Feel free to disagree with the group_concat part, if it doesn't meet your needs; it just lists all of the relevant senders instead of picking one arbitrarily.
Upvotes: 0
Reputation: 3301
Try
SELECT pm_info.is_read, sender.usrFirst as sender_name, pm_data.date_sent, pm_data.title, pm_data.thread_id, pm_data.id as dataid
FROM pm_data, pm_info, tblUsers as sender
WHERE pm_info.message_id = pm_data.id
AND pm_data.sender_id = sender.usrID
AND pm_info.receiver_id = '$usrID'
GROUP BY thread_id
ORDER BY date_sent DESC
LIMIT 0,1
Upvotes: 1