如何组合这些MySQL查询,然后正确访问数据

gor*_*dyr 6 php mysql

我正在我的应用程序中构建一个嵌套的评论回复系统.

一切当前按预期工作,但我发现自己必须使用几个MySQL查询才能检索所需的数据.更糟糕的是,对'回复'的查询是在foreach循环中.这意味着虽然它现在表现令人钦佩,但它远非最佳,并且随着数据集的增长会引起问题.

因此,我希望在进一步深入发展之前解决这个问题.

由于该应用程序的表与该网站的wordpress博客共享相同,因此我使用wordpress简写进行查询.

生成页面的当前方式如下:

查询评论表并检索与项目相关的所有结果: -

    $commentquery = "select projects_comments.*, users.user_url, users.display_name
                 from ".$wpdb->prefix."projects_comments projects_comments
                 left join ".$wpdb->prefix."users users on users.ID=projects_comments.userid
                where projectid = '$projectid'
                order by projects_comments.commentid desc
                ";  

$comments = $wpdb->get_results($commentquery);
Run Code Online (Sandbox Code Playgroud)

然后我执行foreach循环如下: -

   if($comments) {
            foreach ( $comments as $c ) 
                { 


                $replyquery = "select project_replies.*, users.user_url, users.display_name

                 from ".$wpdb->prefix."project_replies project_replies
                 left join ".$wpdb->prefix."users users on users.ID=project_replies.uid
                where project_replies.cid = '$c->commentid' 
                order by project_replies.id desc        
                limit 2         
                ";      

                $replies = $wpdb->get_results($replyquery);

                asort($replies);

                $countquery = "select count(*)

                    from ".$wpdb->prefix."project_replies project_replies
                    where project_replies.cid='".$c->commentid."'
                    ";

                $replycount = $wpdb->get_var($countquery);  

    //generate html here
   }
}
Run Code Online (Sandbox Code Playgroud)

在这个循环中是另外两个查询.第一个得到每个评论的回复但是将结果限制为2(我希望这样做以便有一个"查看所有回复"按钮,然后如果用户需要,则查询数据库以获得其余的),第二个查询计数回复总数.

然后还使用上面循环中的第二个嵌套foreach(在这里生成html代码)为循环内的每个回复生成html,如下所示: -

if ($replies){

    foreach ( $replies as $r ){

     // generate each reply
    }
}
Run Code Online (Sandbox Code Playgroud)

所有数据都以以下方式从这些数组中提取:

$c->userid, $c->body etc... For the comments
$r->userid, $r->body etc... For the replies.
Run Code Online (Sandbox Code Playgroud)

如果可能的话,我希望保留这种格式.

正如在问题开头所述,这一切都完美无缺,但我知道通过嵌套回复和计数查询,我执行的查询比必要的要多得多.100条评论将生成100个回复查询和100个计数回复查询等.

感谢网站上一些乐于助人的人,我考虑过使用联接来一次性获取所有原始数据以进行评论和回复.像这样......

$commentquery2 = "SELECT c.commentid, c.userid, c.body as cbody, c.projectid, c.posttime, cu.user_url AS cu_url, cu.display_name AS cu_name,
                    r.*, ru.user_url AS ru_url, ru.display_name AS ru_name
                FROM ".$wpdb->prefix."projects_comments AS c
                LEFT JOIN ".$wpdb->prefix."users        AS cu ON cu.ID = c.userid
                LEFT JOIN ".$wpdb->prefix."project_replies   AS r  ON r.cid = c.commentid 
                LEFT JOIN ".$wpdb->prefix."users        AS ru ON ru.ID = r.uid
                WHERE c.projectid = $projectid
                ORDER BY c.commentid DESC, r.id DESC";   
Run Code Online (Sandbox Code Playgroud)

虽然这确实有用(并且足以让我将这个问题标记为已回答),但在实践中我遇到了一些困难.

首先,这将所有数据检索为单独的行,这意味着如果我有5条评论,每条评论有3条回复,我实际上会返回15行,而不是嵌套数据对象,并且回复嵌套在每个评论行中.

为了解决这个问题,我尝试了一些数组操作,如下所示:

$old_id=NULL;
$comments=array();

foreach($getcomments as $c){

    if($c->commentid !== $old_id){

        $comments[$old_id] = $c;
        $old_id = $c->commentid;

    }


    $comments[$old_id]['replies'][] = $c;


} 
Run Code Online (Sandbox Code Playgroud)

这样做可以根据需要为我提供嵌套数据对象.但是,它不包括回复计数查询,并且它不会按预期将每组回复限制为2,而是检索所有回复.

最后使用我在foreach循环中的当前html生成代码:

foreach($comments){

    //generate comment html

    foreach($replies) {

         //generate replies html

    }

}
Run Code Online (Sandbox Code Playgroud)

我似乎无法让它与嵌套数据对象一起正常工作.访问正确的深层回复似乎让我感到困惑.

总而言之,我希望能够删除循环查询,将它们组合成一个更大,更高效的查询,或者最坏的情况是将数据查询和单独的计数查询组合在一起,然后创建一个整齐嵌套的数据对象,并将注释作为嵌套在"回复"标题下的行和任何回复

然后我需要能够在我的PHP代码中正确迭代这些以生成所需的html.

我为这个问题的长度道歉,并意识到它可能会让你们许多人不再回答,但我现在已经和你们争斗了19个小时,真的需要帮助.

非常感谢任何提出任何建议的人.

Bur*_*Leo 2

如果您想将评论和回复保留在两个不同的表中(请参阅 crafter 的评论),您可以使用一个简单的技巧来删除循环:从第一个查询中收集评论 ID 并使用

WHERE (cid IN (1,2,3,4,...))

而不是循环。如果您需要限制每个评论的回复,则可以使用附加的 WHERE- 或 HAVING 子句来实现。

伯宁利奥