【问题标题】:Looping through MySQL left join in php vs. 2 separate queries循环通过 MySQL left join in php vs. 2个单独的查询
【发布时间】:2012-06-25 07:22:33
【问题描述】:

我的网站上有一个简单的问答部分,允许使用 cmets。我目前使用循环和 $_GET['id'] 值填充答案。这是我的查询

<?php
try{
   $parent=$_GET['id'];
   $post_type = "2";
   $stmt = $dbh->prepare(
    "SELECT p.post_id, p.content, p.author, p.created, pc.comment_id AS comment_id, pc.content AS comment_content
     FROM posts AS p
     LEFT JOIN posts_comments AS pc
     ON p.post_id = pc.parent_id
     WHERE p.post_type = :post_type AND  p.parent = :parent ");

   $stmt->bindParam(':parent', $parent, PDO::PARAM_INT);
   $stmt->bindParam(':post_type', $post_type, PDO::PARAM_INT);
   $stmt->execute();

   $answers_array = array();
   while ($answers = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $answers_array[]= $answers;
   }
}

?>

这会在一个数组中返回以下结果

   Array ( 
[0] => Array ( 
        [post_id] => 12 
        [content] => I have an answer
        [author] => Author1
        [created] => 2012-06-09 21:43:56
        [comment_id] =>
        [comment_content] => ) 
[1] => Array ( 
        [post_id] => 13
        [content] => My second answer
        [author] => Author1
        [created] => 2012-06-10 06:30:58
        [comment_id] => 35
        [comment_content] => 1st comment ) 
[2] => Array ( 
        [post_id] => 13
        [content] => My second answer
        [author] => Author2
        [created] => 2012-06-10 06:30:58
        [comment_id] => 36
        [comment_content] => 2nd comment ) 
[3] => Array ( 
        [post_id] => 13
        [content] => My second answer
        [author] => Author2 
        [created] => 2012-06-10 06:30:58
        [comment_id] => 37
        [comment_content] => 3rd comment ) 
)

在我的 question.php 页面上,我知道我需要使用类似

的方式遍历这些结果
<?php $answer_count = count($answers_array);
 for($x = 0; $x < $answer_count; $x++) {
 $answers = $answers_array[$x];
}
?>

我的问题-

我不知道是使用两个单独的查询来提取与每个答案关联的 cmets,还是使用我上面的连接并使用 php.ini 构建另一个数组。我不知道如何诚实地做到这一点。如果我使用连接,我想要一个看起来像这样的数组,但我不确定如何使用 php 中的循环来构建它。

     Array ( 
[0] => Array ( 
        [post_id] => 12 
        [content] => I have an answer
        [author] => Author1 
        [created] => 2012-06-09 21:43:56 
        [comment_id] => 
        [comment_content] => ) 
[1] => Array ( 
        [post_id] => 13 
        [content] => My second answer
        [author] => Author1 
        [created] => 2012-06-10 06:30:58 
            Array( 
                   [1] => Array (
                       [comment_id] => 35
                       [comment_content] => 1st comment)
                   [2] => Array (
                       [comment_id] => 36
                       [comment_content] => 2nd comment)
                   [3] => Array (
                       [comment_id] => 37
                       [comment_content] => 3rd comment))

一旦我有了一个这样的数组,我想我可以在 question.php 页面上的原始 php 循环中为每个数组做一个。

【问题讨论】:

  • 与发布大量示例输出相比,发布架构片段更有帮助。
  • 我缩短了输出。我不确定需要多少才能回答这个问题。我将努力将架构放在问题中而不是输出中

标签: php mysql while-loop left-join


【解决方案1】:

一个查询就可以了。正如你所拥有的,可能是更好的选择。你必须找出哪个更有效,让 MySQL 承担压力,或者网络和 PHP 承担压力。让 PHP 比 MySQL 承担压力要好得多,但是 MySQL 具有“内置”功能,例如您想要的分组,然后离开 MySQL 并节省网络流量。

要完成这项工作:将“ORDER BY p.post_id, pc.comment_id”添加到您的查询中 - 这样可以按顺序获取结果。

那么,如果你必须构建成一个数组(虽然你可能可以不使用数组直接处理,但方法类似):

$lastPostID = 0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    if ($lastPostID <> $row['post_id']) {
        $lastPostID  = $row['post_id'];
        $answers[$lastPostID] = array('post_id' => $row['post_id'],
                                      'author_id' => $row['author_id'],
                                      etc
                                      'comments' => array() );
    }
    $answers[$lastPostID]['comments'][] = array('comment_id' => $row['comment_id'], 'coment' => $row['comment'] etc);
}

【讨论】:

  • 谢谢。这很好用。我不得不将第 2 行的 $answers 更改为 $row ,但它给了我预期的结果。现在我将使用嵌套的每个循环来提取数据。
  • 啊 - 很抱歉这个错误和很好的收获。我会尽快解决这个问题,以防其他人复制它!祝项目的其余部分好运。
【解决方案2】:

您需要使用 JOIN 通过单个查询返回所有结果,否则,您将进行多个查询,每个帖子一个查询。发出许多单独的查询会产生很多开销。

如果您想返回极少数的帖子结果,则例外。

请务必按 post_id、comment_id 对查询进行排序。

要遍历合并的结果,它看起来像这样:

$post_id = 0;
foreach($rows as $row) {
  // See if our post changed
  if ($post_id != $row['post_id']) {
    // Display the post and post header
    ..
    // Update the current post_id variable
    $post_id = $row['post_id'];
  }
  // Display the comment
}

【讨论】:

  • 感谢您的回答。我将继续加入我的问题。你知道如何通过循环遍历php中的结果将我返回的当前数组组合到第二个多维数组中吗?
  • @FajitaNachos,我更新了我的答案,提供了更多关于我过去是如何做这样的事情的信息。我认为您不需要单独的数组。
【解决方案3】:

选择权在你。每个都有其优点和缺点。使用单个查询(显然,单个数据库调用和)您只需要循环一次数据集,但您有可能返回重复数据。使用多个查询,您只需要准确地提取您需要的数据,但是(显然,多个数据库调用和)您必须迭代多组数据。

下面是单查询方法的脏实现(相同的基本流程适用于多查询方法,除了评论构建是它自己的循环)。但是基本的想法就在那里。您有一个答案地图,可以在迭代记录时添加/检索它们,并附加 cmets。

while ($answers = $stmt->fetch(PDO::FETCH_ASSOC)) 
{
    $post_id = strval($answers['post_id']);
    if(!array_key_exists($post_id, $answers_array)) {
        $answers_array[$post_id] = array(
            'post_id' => $answers['post_id'],
            // ... assign other stuff ...
            'comments' => array()); //initialize the comments array
    }
    if(!empty($answers_array['comment_id'])) {
        $obj = $answers_array[$post_id];
        $obj['comments'][] = array(
            'comment_id' => $answers['comment_id'], 
            'comment_content' => $answers['comment_content']);
    }
}

【讨论】:

    猜你喜欢
    • 2015-11-29
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-22
    • 2012-09-05
    • 1970-01-01
    相关资源
    最近更新 更多