多线程评论PHP?

多线程评论PHP?,php,mysql,sql,comments,hierarchical-data,Php,Mysql,Sql,Comments,Hierarchical Data,我有一个脚本,我写了回来的评论,但它只是单线程。我希望它是多线程的,但只有这样用户才能回复评论,而不是用户可以回复评论的评论。因此,线程只有两个深度 目前,我在数据库中针对用户id存储注释id 我能想到的做多线程注释的唯一方法是在comments表中有一个parent字段。但是如果我这样做,那么当我用PHP选择注释时,我将不得不执行另一个SELECT命令来为每个注释选择注释子项(如果有的话)。看起来数据库上有很多工作 一定有更好的办法。有什么想法吗?还是教程 有三(四)种备选方案: 一个递归查询

我有一个脚本,我写了回来的评论,但它只是单线程。我希望它是多线程的,但只有这样用户才能回复评论,而不是用户可以回复评论的评论。因此,线程只有两个深度

目前,我在数据库中针对
用户id
存储
注释id

我能想到的做多线程注释的唯一方法是在comments表中有一个
parent
字段。但是如果我这样做,那么当我用PHP选择注释时,我将不得不执行另一个SELECT命令来为每个注释选择注释子项(如果有的话)。看起来数据库上有很多工作

一定有更好的办法。有什么想法吗?还是教程

有三(四)种备选方案:

  • 一个递归查询,用于根据父ID选择所有注释。许多数据库产品都支持这一点,语法取决于数据库类型。查看文档以了解更多信息(搜索“递归”)

  • 如果在每个(子)评论中存储文章id,则只需在一个常规选择查询中选择具有文章id的所有评论即可。您可以使用父ID在页面右父注释下正确显示注释:

    SELECT * FROM comments WHERE article_id = :article_id
    
  • 如果您只需要两个级别的注释,可以使用扩展的where来包括第一级和第二级注释:

    SELECT * FROM comments 
    WHERE parent_id = :article_id
    OR    parent_id IN (SELECT id FROM comments WHERE parent_id = :article_id)
    
  • 也可以使用union all组合具有相同列的两个查询,但由于我假设所有数据都来自同一个表,因此可能不需要它(请参阅上面的extended where子句):


  • 就我个人而言,我会选择选项2,因为它简单(不需要特殊的SQL构造)、高效(1个查询)和灵活(支持任意级别的注释)。

    此查询可能适合您(我不知道您的结构,所以我猜测它):

    从注释a中选择*
    a.comment\u id=b.parent\u coment\u id上的左连接注释b
    b上的左连接注释c.comment\u id=c.parent\u coment\u id
    其中a.comment\u id b.comment\u id
    和a.comment\u id c.comment\u id
    和b.comment_id c.comment_id;
    
    1查询就足够了,您只需循环数据并将其正确存储到数组中,然后循环数组并显示注释。

    这是分层或树结构数据的常用方法。我写了一个关于堆栈溢出问题的流行答案:

    我还编写了一个演示文稿,描述了树结构数据的备选方案:

    我的演示文稿中未包含的另一个解决方案是Slashdot处理线程注释的方式。他们像您一样使用
    parent
    列,因此每个注释都引用它所回复的注释。但是,它们还包括一个
    root
    列,这样每个注释都知道它所属的帖子。给定帖子上的评论很少超过几百条,通常您希望从评论线程的顶部开始获取给定帖子的整个评论树:

    SELECT * FROM comments WHERE root = 1234;
    

    然后,在获取注释时,可以编写PHP代码,根据
    parent
    列将它们处理成数组(这就是@JanL的回答所提到的)。我在回答另一个堆栈溢出问题时发布了这样做的代码。

    这是多个查询!这就是我本来应该这样做的,我正在寻找更好的方法。你说的是使用另一个SELECT语句,我给了你一个更好的方法。不,你的解决方案仍将使用多个SELECT。谢谢你的回答。如果你为每个评论存储文章id,你只需要一个SELECT语句,即:
    SELECT*FROM comment WHERE article\u id=:article\u id
    我的解决方案使用1个查询,但不超过1个。这似乎是正确的。我假设第二个左连接和第二个和用于连接第三级评论?请注意,这最多适用于3级评论,并且不会过滤实际文章,我认为这会很有用。嗯。这是结尾。我更多的是寻找一种选择它们的方法,但将它们作为一个单独的行。然后,你需要一个联合而不是一个连接(或递归查询),而不阅读问题的上下文。由于“多线程”和“注释”,这个问题毫无意义我知道这是一篇老文章,但我一直在使用你描述的方法。如果你有一篇评论达数千条的文章,你显然不会选择所有行,但是如果你使用了限制,你将失去树状结构。。。有办法解决这个问题吗?。。。问候J@jon,您可以在注释日期之前使用“限制但顺序”。所以你会得到最古老的评论。然后,如果用户想要展开线程,他们可以请求它,但默认情况下,他们只能看到讨论的一个子集。如果您想了解更多详细信息,请下载Slashdot源代码并查看他们是如何做到这一点的。感谢您的回复,但是如果我理解正确,这将只显示原始的评论线程,如果他们想扩展评论线程以查看任何回复,您将在该评论线程上进行选择,但是我确实希望在第一个查询中也显示评论线程的回复,但也能限制吗?。。是否可以使用邻接层次结构?。。再次感谢J.@jon,不,如果您使用MySQL并且希望支持任意深度的评论回复线程,那么在一个查询中的邻接层次结构是不可能的。这就是为什么人们提出了存储分层数据的替代方法(请参阅我链接到的演示文稿)。其他数据库支持使用公共表表达式进行递归查询,因此这是可能的。感谢您的持续帮助。。。我已经看了你上面链接的文章,以及我所理解的(我仍然是lea)
    SELECT * FROM comments a
    LEFT JOIN comments b ON a.comment_id = b.parent_coment_id
    LEFT JOIN comments c ON b.comment_id = c.parent_coment_id
    WHERE a.comment_id <> b.comment_id
          AND a.comment_id <> c.comment_id
          AND b.comment_id <> c.comment_id;
    
    SELECT * FROM comments WHERE root = 1234;