Scarface
Scarface

Reputation: 3913

mysql grouping question

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

There are two types of 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?

Upvotes: 0

Views: 73

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 753725

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.

Upvotes: 2

Related Questions