Looping через MySQL левое соединение в php против 2 отдельных запросов

У меня есть простой раздел вопросов и ответов на моем веб-сайте, который позволяет делать комментарии. В настоящее время я заполняю ответы, используя цикл и значение $ _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]; } ?> 

Мой вопрос –

Я не знаю, использовать ли два отдельных запроса, чтобы вытащить комментарии, связанные с каждым ответом, или использовать соединение, которое у меня есть, и создать другой массив с php. Я не знаю, как это сделать честно. Если я использую объединение, мне нужен массив, который выглядит так, но я не уверен, как его построить, используя цикл в 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)) 

Как только у меня есть такой массив, я думал, что могу сделать это для каждого внутри моего исходного php-цикла на странице question.php.

Один запрос в порядке. Как у вас есть, и, вероятно, лучший вариант. Вы должны решить, какая из них более эффективна, чтобы заставить 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); } 

Выбор ваш. У каждого есть свои преимущества и недостатки. Используя один запрос (очевидно, один вызов базы данных и), вам нужно только один раз выполнить цикл над вашим набором данных, но у вас есть потенциал для возврата дублированных данных. Используя несколько запросов, вы только отталкиваете именно нужные вам данные, но (очевидно, несколько вызовов в базе данных) и вам нужно перебирать несколько наборов данных.

Ниже приведена грязная реализация метода одиночного запроса (тот же базовый поток применяется к методу с несколькими запросами, за исключением того, что построение комментариев – это собственный цикл). Но основная идея есть. У вас есть карта ваших ответов, добавление / извлечение их при повторном выполнении записей и добавление комментариев.

 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']); } } 

Вы хотите использовать 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 }