简体   繁体   中英

How to sort data with a parent / child relationship

I'm storing threads for a forum with a parent / child relationship as follows:

CREATE TABLE forum_threads (
  thread_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  parent_id INTEGER UNSIGNED NOT NULL DEFAULT 0,
  topic_id INTEGER UNSIGNED NOT NULL,
  user_id INTEGER UNSIGNED NOT NULL,
  title VARCHAR(100) NOT NULL,
  body TEXT NOT NULL,
  create_date DATETIME NOT NULL,

  PRIMARY KEY (thread_id),
  FOREIGN KEY (parent_id)
    REFERENCES forum_threads(thread_id),
  FOREIGN KEY (topic_id)
    REFERENCES forum_topics(topic_id),
  FOREIGN KEY (user_id)
    REFERENCES users(user_id)
);

New threads have parent_id = 0 , whereas replies have parent_id = the thread being replied to . Now where I'm confused is, I want to display a list of threads ordered by the most recent reply:

SELECT * FROM forum_threads
WHERE topic_id = :topic_id AND parent_id = 0
ORDER BY ??? DESC LIMIT :start, :display

Not sure how to accomplish this?

If a parent can't have a parent, you can use a query like this:

SELECT *
FROM forum_threads
ORDER BY
  CASE WHEN parent_id=0 THEN thread_id ELSE parent_id END DESC,
  Parent_id!=0,
  thread_id DESC

This will list all threads in descending order, with replies ordered by the most recent one.

If I understand the structure correctly, the replies are those rows with a parent_id that point to the thread_id of the "parent" thread.

If that's the case, a self-join like this will work - note that the SELECT * has to go because (a) you're selecting from two tables so * means "all the rows in both tables" and (b) you need to GROUP BY specific columns:

SELECT
  parent.thread_id,
  parent.parent_id,
  parent.topic_id,
  parent.user_id,
  parent.title,
  parent.body,
  parent.create_date,
  MAX(reply.create_date) AS reply_date
FROM forum_threads parent
INNER JOIN forum_threads reply ON parent.thread_id = reply.parent_id
WHERE topic_id = whatever AND parent_id = 0
GROUP BY
  parent.thread_id,
  parent.parent_id,
  parent.topic_id,
  parent.user_id,
  parent.title,
  parent.body,
  parent.create_date
ORDER BY reply_date DESC

Something like this would also work:

SELECT * FROM forum_threads `t1`
WHERE topic_id = :topic_id AND parent_id = 0
ORDER BY (SELECT `create_date` FROM `forum_threads` WHERE `parent_id`=`t1`.`thread_id` ORDER BY `create_date` DESC LIMIT 1) DESC LIMIT :start, :display

Ed Gibbs' solution is better if you need to access the replied to date (mine would require another subquery) but if you don't need it, this is a simpler solution (IMHO).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM