views:

29

answers:

1

Hey guys, quick question. I have a table of messages.

There are two types of messages:

  • Messages with a unique group id
  • autonomous messages

Messages with the same group id as at least one other message - these I want to group together when they are presented. The grouped messages are messages with replies to them. What I want to do is create a query in order to put the grouped messages together in the place where the earliest/root message of that group would be in relation chronologically with the rest of the messages regardless of the time the replies are entered.

my current query is this, and obviously only sorts messages chronologically.

  SELECT timestamp, 
         user, 
         message, 
         group_id 
    FROM messages 
   WHERE topic_id = ? 
ORDER BY timestamp DESC 
   LIMIT 10

Does anyone have any suggestions?

+2  A: 

What about this?

SELECT m.timestamp, m.user, m.message, m.group_id, g.grp_timestamp
  FROM messages AS m JOIN
       (SELECT group_id, MIN(timestamp) AS grp_timestamp
          FROM messages
         GROUP BY group_id) AS g ON m.group_id = g.group_id
 WHERE m.topic_id = ?
 ORDER BY g.grp_timestamp, g.group_id, m.timestamp;

The logic is to identify the earliest timestamp for each group_id in the sub-query (presuming messages with no responses have a valid group_id assigned) and then sort first by the group timestamp, then by group ID (so that if two groups end up with the same timestamp somehow, the messages are still sorted correctly), and then by the message timestamp.

You might want to push the WHERE clause into the sub-select too.


If you want the most recent messages first, then basically, you apply DESC to the ORDER BY clause in the appropriate places.

SELECT m.timestamp, m.user, m.message, m.group_id, g.grp_timestamp
  FROM messages AS m JOIN
       (SELECT group_id, MIN(timestamp) AS grp_timestamp
          FROM messages
         GROUP BY group_id) AS g ON m.group_id = g.group_id
 WHERE m.topic_id = ?
 ORDER BY g.grp_timestamp DESC, g.group_id, m.timestamp DESC;

You might want the group with the most recent response to appear first; in that case, you need to adjust the aggregate from MIN to MAX:

SELECT m.timestamp, m.user, m.message, m.group_id, g.grp_timestamp
  FROM messages AS m JOIN
       (SELECT group_id, MAX(timestamp) AS grp_timestamp
          FROM messages
         GROUP BY group_id) AS g ON m.group_id = g.group_id
 WHERE m.topic_id = ?
 ORDER BY g.grp_timestamp DESC, g.group_id, m.timestamp;

As long as you are OK with the responses appearing in chronological order, I think that does the trick. If the responses must appear in reverse chronological order with the original message appearing first, you have some difficulties. If you tagged the messages with 'L' for 'leader' and 'F' for 'follower' in the messages table, then you can use that column to do the sorting. If you have to dynamically determine whether a message is a leader or follower, you have to work harder.

Jonathan Leffler
First of all, thanks a lot for your time Jonathan. it seems to work,since the group is grouped and the group itself is in the right chronological order but I would like to reverse the order of the results within the group by using desc or asc on the , how would I do so with this query?
Scarface
Quite an epic response Jonathan. I really appreciate your efforts and time in helping me with this issue and going above and beyond in explaining the possibilities in solving it. Thanks again.
Scarface