【问题标题】:MySQL self join with limited hierarchy具有有限层次结构的 MySQL 自联接
【发布时间】:2015-02-13 19:45:26
【问题描述】:

您好,我有一个用于 cmets 和回复的自连接 MySQL 表。

CREATE TABLE comments (id INT, parent_id INT, comment VARCHAR(50));

INSERT INTO comments VALUES
 (1,     0,           'comment 1'            ),
 (2,     0,           'comment 2'            ),
 (3,     0,           'comment 3'            ),
 (4,     1,           'comment 1 - reply 1'  ),
 (5,     0,           'comment 4'            ),
 (6,     3,           'comment 3 - reply 1'  ),
 (7,     1,           'comment 1 - reply 2'  ),
 (8,     0,           'comment 5'            );

只有一个级别的回复。也就是说,回复只能与顶级评论相关联(其中 parent_id = 0)。

我使用以下查询来显示每个顶级评论(其中 parent_id = 0)和每个与 cmets 相关的回复。

SELECT *
FROM comments 
ORDER BY IF(parent_id = 0, id, parent_id) desc , parent_id != 0, id desc

输出:

id  parent_id   comment
-------------------------
8      0        comment 5
5      0        comment 4
3      0        comment 3
6      3        comment 3 - reply 1
2      0        comment 2
1      0        comment 1
7      1        comment 1 - reply 2
4      1        comment 1 - reply 1

当前查询可以很好地满足我的需要。

我的问题是如何限制每条评论的回复数量?例如。显示最新的 50 个顶级 cmets,每条评论最多回复 2 条。

Here is a SqlFiddle if it helps

【问题讨论】:

    标签: mysql sql hierarchy self-join


    【解决方案1】:

    试试这个:

    编辑:

    SELECT pc.id,
           pc.parent_id,
           pc.comment
      FROM (
              SELECT id,
                     parent_id,
                     comment,
                     @parentRank := @parentRank + 1 AS rank
                FROM comments,
                     (SELECT @parentRank := 0) pcr
               WHERE parent_id = 0
            ORDER BY id DESC                      
           ) pc
     WHERE pc.rank <= 5
     UNION
    SELECT cc.id,
           cc.parent_id,
           cc.comment
      FROM (
              SELECT id,
                     parent_id,
                     comment,
                     @childRank := if(@current_parent_id = parent_id, @childRank + 1, 1) AS rank,
                     @current_parent_id := parent_id
                FROM comments,
                     (SELECT @childRank := 0) cr
               WHERE parent_id in (
                                    SELECT id
                                      FROM (
                                             SELECT id,
                                                    @parentRank := @parentRank + 1 AS rank
                                               FROM comments,
                                                    (SELECT @parentRank := 0) pcr
                                              WHERE parent_id = 0
                                           ORDER BY id DESC                      
                                           ) pc
                                     WHERE pc.rank <= 5
                                  ) 
            ORDER BY parent_id DESC,
                     id DESC
                 ) cc
           WHERE cc.rank <= 1
    ORDER BY IF(parent_id = 0, id, parent_id) desc , parent_id != 0, id desc
    

    我在SQLFiddler做了一个演示

    【讨论】:

    • 这似乎只显示有回复的顶级 cmets。那是对的吗?我需要显示所有顶级 cmets,并且每条评论最多回复 2 条。
    • 好的,我明白了,我更改了查询,您可以使用WHERE 条件和排序顺序来决定要显示哪些 cmets 和子 cmets
    • 太棒了,效果很好。我还想出了下面的另一个解决方案。非常感谢。
    【解决方案2】:

    Limit(offset)的第一个参数控制回复的数量

    SELECT *, 
    
    (SELECT COUNT(id) FROM comments r where r.parent_id = c.id) AS number_of_replies
    
    FROM comments c
    
    WHERE IFNULL((SELECT e.id FROM comments e WHERE e.parent_id != 0 AND 
        e.parent_id = c.parent_id ORDER BY e.id DESC LIMIT 2, 1), 0) < c.id
    
    ORDER BY IF(parent_id = 0, id, parent_id) desc , parent_id != 0, id desc
    

    【讨论】:

      猜你喜欢
      • 2018-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-20
      相关资源
      最近更新 更多