【问题标题】:MySQL to group child comments under parent comments is not returning correct data resultMySQL在父评论下对子评论进行分组未返回正确的数据结果
【发布时间】:2015-06-10 05:22:22
【问题描述】:

我正在构建的 JavaScript/PHP/MySQL 项目管理应用程序有一个面板/div,可以加载属于项目任务记录的所有事件/评论记录

这些活动事件日志记录讲述了对任务记录所做修改的历史记录。他们在同一个流程中也有任务注释。

我现在正在尝试添加 Comment threading/child/sub-cmets。

我下面的屏幕截图显示了从右上角向下的第 5 条记录中的一个示例,它是一个缩进的评论,它似乎是它上面的评论记录(第 4 号)的子评论/子评论。

click to view full size image

现在,如果您查看 DOM HTML 结构,您会发现子注释与 HTML 流中的父注释没有什么不同。这意味着子注释不是 HTML 中的子节点。相反,子评论位于父评论下方,并且只是有一个 CSS 类来表示它是应用 margin-left CSS 值和更小的 width 的子评论。


MySQL 数据库表

--
-- Table structure for table `updates_stream`
--

CREATE TABLE IF NOT EXISTS `updates_stream` (
`id` int(18) NOT NULL,
  `event_type` varchar(10) DEFAULT 'comment',
  `comment_id` int(36) DEFAULT NULL,
  `comment_parent_id` int(36) DEFAULT '0',
  `record_id` char(36) DEFAULT NULL,
  `modified_user_id` int(36) DEFAULT NULL,
  `record_name` varchar(255) DEFAULT NULL,
  `date_entered` datetime DEFAULT NULL,
  `date_modified` datetime DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=1092 DEFAULT CHARSET=utf8;

我试图用来获取 Parnet cmets 下的子 cmets 的 SQL 查询(不希望的结果)

SELECT * FROM updates_stream AS parent
LEFT JOIN updates_stream AS child 
ON child.comment_parent_id = parent.id
WHERE parent.comment_parent_id = '0'
ORDER BY parent.id, child.id;

现在回答我的问题...

如何查询 MySQL 以正常获取所有记录,但现在我需要将所有子 cmets 放在父 cmets 下。

我上面的 MYSQL 代码是在 SQLFiddle 演示 上设置的,以便在此处进行测试:http://sqlfiddle.com/#!9/08396/4

我需要什么:

根据我的要求,有6条记录的demo的输出应该是这个ID顺序:

-- ID=1
-- ID=2
------- ID=3: child comment ID 3 has a Parent ID comment of 2
------- ID=5: child comment ID 5 has a Parent ID comment of 2
-- ID=4
-- ID=6

我得到了什么(坏了!):

相反,演示的结果如下所示...只有 5 行而不是全部 6 行。 ID 为 2 的 COMmment 连续列出 2 次,这有点正确,几乎意味着有子 cmets 的 1 条评论是ID2 有 2 个子 cmets。此外,如果您滚动到页面右侧的 ID2 行,您实际上会在右侧看到 ID 3 和 5,但在同一列中!:

-- ID=1
-- ID=2  ==>  ID3
-- ID=2  ==>  ID5
-- ID=4
-- ID=6

【问题讨论】:

  • 我假设有孩子对孩子的可能性对吗?

标签: mysql join


【解决方案1】:

我不知道你想要的能不能是SQL。不过,我在 php 中对嵌套菜单做了类似的事情,它应该在这里工作。

首先,对您的查询稍作改动:

SELECT 
    * 
FROM 
    updates_stream
ORDER BY comment_parent_id;

为此,我们还需要为您的 cmets 定义一个类:

class Comment{
    public $id;
    public $comment = '';
    ....
    //Do not need any reference to the parent.
    //Used to tell how nested the comment is (Child of child, etc.)
    public $nest_lvl = 0;
    public $children = array();

    public function generateHtml(){...}
}

所以我们要做的是遍历我们的结果集,为每个评论创建一个类的实例。我们将有两个数组,一个用于设置格式,另一个用于轻松访问父 cmets:

$parentComments = array();
$nestedComments = array();

while($row = mysqli_fetch_assoc($result)){
    $comment = new Comment();
    //Set comment values;

    if($row['parent_id'] != 0){
        //Add this comment to the parent comment children array
        $comment->nest_lvl = $parentComments[$row['parent_id']]->nest_lvl + 1;
        $parentComments[$row['parent_id']]->children[] = $comment;
    } else {
        //Add this comment to the nested array. Only comments that are not a child
        //comment should be added to the nested array, otherwise they will display twice.
        $nestedComments [] = $comment;
    }

    //Add this comment to the parent array
    $parentComments[$comment->id] = $comment;
 }

 unset($parentComments);
 mysqli_free_result($result);

由于我们使用类,所以一切都是通过引用完成的。因此,当我们更改$parentComments 中的类的实例时,更改也会反映在$nestedComments 中的同一类实例中。

回到Comment 类中的函数。此函数将生成父注释 AND 其所有子注释所需的 HTML(递归)。所以这个函数的实现看起来像这样:

public function generateHtml(){
    //Generete the html for the current comment.
    //If the children array is not empty, call generateHtml on each of them.
    foreach($this->children as $child){
        $child->generateHtml();
    }
}

您可以选择将嵌套 lvl 传递给函数,而不是在类中。

最后,要显示所有内容,只需循环遍历$nestedComments,对它们中的每一个调用generateHtml()

foreach($nestedComments as $comment){
    $comment->generateHtml();
}

虽然它不是全部在 SQL 中,但它会完成工作并且比在 SQL 中更容易完成。

【讨论】:

    猜你喜欢
    • 2012-08-23
    • 2021-09-27
    • 2021-12-30
    • 1970-01-01
    • 2021-03-14
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多