Nested comment system mysql ordering

可紊 提交于 2020-08-11 01:47:05

问题


Ok, I realize there are many ways to accomplish comments. The way I have chosen is a single table set up like this.

id    comment    date       time    orig_comment
1     Hello   03-01-2013  10:10:10       0
2     Hello   03-02-2013  10:10:10       0
3     Hello   03-03-2013  10:10:10       1

So to clearify there is a first level and then users can reply to that comment(these are the only two levels). I give each unique incrementing id, and specify orig_comment. If orig_comment is "0" then it is a base level comment, if it is nested then orig_comment will be the id of the original comment. Simple enough. So I need the comments to be ordered of course. Here is how I do this as of now.

mysql_query("SELECT Comments.* FROM Comments ORDER BY 
IF(Comments.orig_comment = 0, Comments.id, Comments.orig_comment)DESC,Comments.id ASC")

This works to get the newest comments retrieved first(which is what I want), but when it comes to nested comments it orders them by oldest first(not what I need). I need to order primary comments from newest to oldest, and any replies should be ordered also from newest to oldest. I have tried without success to modify my query to do this but cannot figure it out.

As a side question does this system make sense from a usabality standpoint? Do you think ordering nested comments that way would be confusing? I wanted to do it this way because my reply button is located on the base comment, and once clicked adds a textarea right below the base comment. I just thought it would be easier to see your post if it too came right below the base comment instead of being thrown all the way to the bottom of the nested replies. Any thoughts on this?

Also want to address another question I have using this to page comments. I can use a simple limit to get only the x number of comments like this:

mysql_query("SELECT Comments.* FROM Comments ORDER BY 
IF(Comments.orig_comment = 0, Comments.id, Comments.orig_comment)DESC,Comments.id ASC 
LIMIT 0, $page")

This method obviously does not pay attention to the number of replies to each main comment. So I end up cutting off replies to the very last main comment. I would like to enforce the limit only when orig_comment='0', so that no matter how many replies there are to a comment it will show all of them. I tried

mysql_query("SELECT Comments.* FROM Comments ORDER BY 
IF(Comments.orig_comment = 0, Comments.id, Comments.orig_comment)DESC,Comments.id ASC 
LIMIT 0, SELECT COUNT(id)FROM Comments WHERE orig_comment='0' LIMIT $page")

This throws a syntax error though.


回答1:


Consider this example...

 DROP TABLE IF EXISTS comments;

 CREATE TABLE comments
 (comment_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
 ,comment VARCHAR(50) NOT NULL   
 ,comment_date DATETIME
 ,parent_id INT NULL
 );

 INSERT INTO comments VALUES
 (1     ,'Hello',                           '2013-03-01 10:10:10',NULL),
 (2     ,'Bonjour',                         '2013-03-02 10:10:10',NULL),
 (3     ,'How are you?',                    '2013-03-03  10:10:10',1),
 (4     ,'I\'m fine thank you, and you?',   '2013-03-04 10:10:10',1),
 (5     ,'Ça va?',                          '2013-03-05 10:10:10',2),
 (6     ,'Je vais bien, merci, et toi?',    '2013-03-06 10:10:10',2),
 (7     ,'Yes, not too bad thanks',         '2013-03-07 10:10:10',1),
 (8     ,'Oui, comme ci comme ça.',         '2013-03-08 10:10:10',2),
 (9     ,'Bon, à bientôt.',                 '2013-03-09 10:10:10',2),
 (10    ,'See you soon',                    '2013-03-10 10:10:10',1);

 SELECT * 
   FROM comments 
      x 
   JOIN comments y 
     ON y.parent_id = x.comment_id 
  ORDER 
     BY x.comment_date
      , y.comment_date;
 +------------+---------+---------------------+-----------+------------+------------------------------+---------------------+-----------+
 | comment_id | comment | comment_date        | parent_id | comment_id | comment                      | comment_date        | parent_id |
 +------------+---------+---------------------+-----------+------------+------------------------------+---------------------+-----------+
 |          1 | Hello   | 2013-03-01 10:10:10 |      NULL |          3 | How are you?                 | 2013-03-03 10:10:10 |         1 |
 |          1 | Hello   | 2013-03-01 10:10:10 |      NULL |          4 | I'm fine thank you, and you? | 2013-03-04 10:10:10 |         1 |
 |          1 | Hello   | 2013-03-01 10:10:10 |      NULL |          7 | Yes, not too bad thanks      | 2013-03-07 10:10:10 |         1 |
 |          1 | Hello   | 2013-03-01 10:10:10 |      NULL |         10 | See you soon                 | 2013-03-10 10:10:10 |         1 |
 |          2 | Bonjour | 2013-03-02 10:10:10 |      NULL |          5 | Ça va?                       | 2013-03-05 10:10:10 |         2 |
 |          2 | Bonjour | 2013-03-02 10:10:10 |      NULL |          6 | Je vais bien, merci, et toi? | 2013-03-06 10:10:10 |         2 |
 |          2 | Bonjour | 2013-03-02 10:10:10 |      NULL |          8 | Oui, comme ci comme ça.      | 2013-03-08 10:10:10 |         2 |
 |          2 | Bonjour | 2013-03-02 10:10:10 |      NULL |          9 | Bon, à bientôt.              | 2013-03-09 10:10:10 |         2 |
 +------------+---------+---------------------+-----------+------------+------------------------------+---------------------+-----------+



回答2:


Thanks to the answer in your comment and I tried out and found a solution, it's not very beautiful but it seems to get the job done.

SELECT *, CASE orig_comment
    WHEN 0 THEN CONCAT_WS('.',id,LPAD((SELECT MAX(id)+1 FROM Comments WHERE orig_comment = C.id),3,'0'))
    ELSE CONCAT_WS('.',orig_comment,LPAD(id,3,'0'))
END AS sort
FROM Comments as C
ORDER BY sort DESC

output will be:

id  comment time        orig_comment    sort
2   Hello   "2013-03-21 16:19:00"   0   2.005
3   Hello   "2013-03-21 16:19:00"   2   2.003
4   Hello   "2013-03-21 16:19:00"   2   2.004
1   Hello   "2013-03-21 16:19:00"   0   1

This will not be troublesome when sorting, and allows up to 999 sub-comments (due to LPAD value 3) What it does is creates a sorting string, and then casts it to a decimal to get the sorting right. (however i think mysql does handle it right anyways.)

Even though this works I recommend computing the sorting value pre-hand hand, then create a good value for base level comments. (maybe set it to 2.9 or whatever will suit your needs)



来源:https://stackoverflow.com/questions/15538168/nested-comment-system-mysql-ordering

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!