Список категорий с последними комментариями / действиями с MYSQL - PullRequest
3 голосов
/ 05 августа 2009

Я занимаюсь разработкой сайта, где пользователи могут оставлять комментарии, и каждый комментарий классифицируется. У меня есть страница, на которую пользователи могут перейти и просмотреть список всех категорий на сайте с последними 5 опубликованными комментариями.

Информация, которую мне нужно получить из базы данных:

  • Список категорий
    • 5 комментариев в каждой категории

Это то, что у меня есть сейчас (упрощено до базового PHP):

echo "<ul>";
$query = mysql_query("SELECT * FROM categories");
while($result = mysql_fetch_assoc($query)){

    echo "<li><h2>{$result['category_name']}</h2>";

    $query_comments = mysql_query(
                                 "SELECT * FROM comments WHERE ".
                                 "category_id = '{$result['id']}' ".
                                 "ORDER BY created_at DESC LIMIT 5");
    while($result_comments = mysql_fetch_assoc($query_comments)){
        echo "{$result_comments['username']} wrote {$result_comments['text']} on {$result_comments['created_at']}<br>";
    }

    echo "</li>";

}
echo "</ul>";

Это выглядело бы так (при условии, что мои категории называются фруктами)

Apple
    Jay wrote blah blah blah - August 5, 2009
    Bob wrote hello hello hello - August 5, 2009
    Tom wrote super super - August 5, 2009
    Edward wrote no no no - August 5, 2009
    Kaysie wrote super no! - August 5, 2009

Orange
    Cassie wrote ye ye ye ye - August 5, 2009
    Alfonce wrote whoohoo - August 5, 2009
    Arthur wrote love oranges - August 5, 2009
    Alice wrote yes yes yes - August 5, 2009
    Xavier wrote Lorem ipsum dolor sit amet - August 5, 2009

Strawberry
    Chris wrote Lorem ipsum dolor sit amet - August 5, 2009
    Hubert wrote Lorem ipsum dolor sit amet - August 5, 2009
    Martin wrote Lorem ipsum dolor sit amet - August 5, 2009
    Lyon wrote Lorem ipsum dolor sit amet - August 5, 2009
    Paris wrote Lorem ipsum dolor sit amet - August 5, 2009

Blueberry
    etc...

Проблема в том, что если категорий много, у меня будут проблемы с производительностью, особенно если на сайте много пользователей.

Я изо всех сил пытаюсь найти способ уменьшить количество необходимых запросов. У кого-нибудь есть идеи, как мне это сделать?

ОБНОВЛЕНИЕ Я пытался ВЛЕВО СОЕДИНИТЬСЯ с таблицей категорий с таблицей комментариев, однако я не нашел способа ограничить количество комментариев на категорию, потому что если я использую LIMIT 5, он ограничивает Количество комментариев возвращено.

Ответы [ 4 ]

2 голосов
/ 05 августа 2009

Вы можете использовать соединение:

SELECT categories.category_name, comments.*
FROM comments 
LEFT JOIN categories ON categories.category_id=comments.category_id

и измените способ перебора результатов.

2 голосов
/ 05 августа 2009

Я поговорил с парнем из базы данных, и в MySQL это немного болезненно.

Примерно так будет хорошо работать в PostgreSQL:

SELECT * FROM categories
LEFT JOIN comments ON categories.id = comments.category_id
WHERE comments.id IS NULL OR
comments.id IN ( SELECT id FROM comments AS a2 WHERE categories.id = a2.category_id ORDER BY id DESC LIMIT 5 )

К сожалению, MySQL не поддерживает LIMIT в подзапросах. Он почесал голову и сказал, что есть обходной путь, но он звучит не очень красиво. В тот момент я подумал, что вы также можете использовать несколько запросов. Если это проблема с производительностью, это могут быть данные, которые вы временно кэшируете.

Извините, не сильно помогло:)

Старый неправильный ответ: Попробуйте использовать ЛЕВОЕ СОЕДИНЕНИЕ в своем запросе с категориями слева (поэтому все категории всегда возвращаются, независимо от того, есть ли у них комментарии) и таблицей комментариев справа. Это уменьшит его до одного запроса.

0 голосов
/ 05 августа 2009

Я не вижу весь ваш код, но я действительно думаю, что вы должны сделать функцию

get_categories()
{
    //PSEUDO: $results_array;
    //PSEUDO: return $results_array = mysql_results;
}

Если у вас есть время, я бы предложил перейти на PDO

тогда ваш HTML будет:

// rough PSEUDO Code
<ui>
    <li>
         <?php 
             foreach ($results_array as $key => $value)
             {
                 echo(htmlentitites($value);
             }
         ?>

    </li>


</ui>

Таким образом, вы перемещаете свой код в более организованную структуру.

0 голосов
/ 05 августа 2009

Что-то вроде этого, возможно?

SELECT cat.*, com.*
FROM categories cat, comments com
WHERE com.categoryid=cat.id
ORDER BY cat.category_name ASC, com.created_at DESC

Примечание. Было бы разумнее расширить *, чтобы выбрать только то, что вам нужно (а также устранить любую вероятность неоднозначности).

РЕДАКТИРОВАТЬ: после более внимательного прочтения я не думаю, что вы хотите получить этот или какой-либо другой ответ, поскольку он будет получать все комментарии из базы данных, а не только последние.

Лучшее решение, которое я могу придумать сейчас, это чтобы вы сами выбрали, сколько лет назад игнорируется, и добавьте com.created_at > [date], чтобы ограничить общее количество выбранных комментариев. Это может означать, что некоторые категории не показывают 5 комментариев, даже если пользователь сделал 5 или более, но давно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...