Как я могу удалить этот запрос из цикла? - PullRequest
3 голосов
/ 03 апреля 2010

В настоящее время я разрабатываю форум как личный проект. Одна из повторяющихся проблем, с которыми я сталкивался, - это запросы к базе данных в циклах. До сих пор мне удалось избежать этого, используя объединения таблиц или кэширование данных в массивах для последующего использования.

Прямо сейчас, хотя я столкнулся с ситуацией, когда я не уверен, как я могу написать код таким образом, чтобы я мог легко использовать любой из этих методов. Однако я все же предпочел бы выполнить не более 2 запросов для этой операции, а не 1 + 1 на группу форумов, что до сих пор приводило к 5 на страницу. Поэтому, хотя число 5 невелико (хотя оно будет увеличиваться для каждой добавляемой группы форумов), для меня здесь важен принцип, я НЕ хочу писать запросы в циклах

То, что я делаю, - это отображение групп индексов форумов (например, форумов администраторов, форумов пользователей и т. Д.), А затем каждого форума в этой группе в одном индексе страниц, это сочетание обоих на одной странице вызывает у меня проблему. Если бы это была всего одна группа на страницу, я бы использовал объединение таблиц и проблема была решена. Но если я использую здесь соединение таблиц, хотя я потенциально могу получить все нужные мне данные, они будут представлены в виде одной массы результатов и должны отображаться правильно.

Вот код (я убрал часть HTML для ясности)

<?php
    $sql= "select * from forum_groups"; //query 1
    $result1 = $database->query($sql);
    while($group = mysql_fetch_assoc($result1)) //first loop
      {?>
        <table class="threads"> 
        <tr>
              <td class="forumgroupheader"> <?php echo $group['group_name']; ?> </td>
            </tr>
            <tr> 
          <td class="forumgroupheader2"> <?php echo $group['group_desc']; ?> </td>
            </tr>
       </table>
       <table>
        <tr>
        <th class="thforum"> Forum Name</th>
        <th class="thforum"> Forum Decsription</th>
        <th class="thforum"> Last Post </th>
        <tr>
            <?php 

                $group_id = $group['id'];
                $sql = "SELECT forums.id, forums.forum_group_id, forums.forum_name, forums.forum_desc, forums.visible_rank, forums.locked, forums.lock_rank, forums.topics, forums.posts, forums.last_post, forums.last_post_id, users.username
FROM forums 
LEFT JOIN users on forums.last_post_id=users.id 
WHERE forum_group_id='{$group_id}'";
                //query 2
                $result2 = $database->query($sql);
                while($forum = mysql_fetch_assoc($result2))
                                            //second loop        
                    {?>

Так как же я могу
а) написать SQL таким образом, чтобы удалить второй запрос из цикла или
б) объединить результаты в массив
В любом случае мне нужно иметь возможность доступа к данным как к тому моменту, когда я смогу правильно отформатировать их для вывода страницы, то есть внутри неподвижных циклов.

Ответы [ 2 ]

3 голосов
/ 03 апреля 2010

Вы можете сделать это с двумя запросами. Первый запрос не нуждается в изменении (хотя лично я предпочел бы не использовать SELECT *). Второй запрос необходимо изменить, чтобы он присоединился к forum_groups и выполнялся вне цикла, прежде чем начать итерацию:

SELECT forum_groups.id, ...other columns here...
FROM forum_groups 
JOIN forums ON forum_groups.id = forum_group_id
LEFT JOIN users ON forums.last_post_id = users.id

Вы также можете объединить эти два запроса в один огромный запрос, который извлекает все данные за один раз, но я бы, вероятно, этого не сделал, так как это потребует возврата избыточных данных.

2 голосов
/ 03 апреля 2010

Я не думаю, что ваш подход настолько плох, и я бы не стал его менять. Однако в качестве упражнения вы можете сделать все это одним запросом, если выберете форумы (присоединитесь к группе) и упорядочите по идентификатору группы. Таким образом, вы сделали только один выбор, и вы можете начать цикл. В вашем цикле вы бы проверили, изменился ли group_id. Если это так, тогда начинайте новый заголовок группы.

Если это сайт со сверхвысоким трафиком, вы можете также изучить кэширование, чтобы страницы записывались на диск после их создания.

Вот пример того, как вы можете обнаружить изменение группы:

$currentGroupId = 0;
$firstTime = true;
while ($row = mysql_query_fetch_assoc($res)) {
    if ($row['group_id'] != $currentGroupId) {
        $currentGroupId = $row['group_id'];
        if (!$firstTime) {
            // echo close group html
        } else {
            $firstTime = false;
        }
        // echo open group html
    }

    // do forum stuff
}
// echo close group html
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...