Самый эффективный способ запросить новейшие 20 сообщений в категории на странице Sme - PullRequest
0 голосов
/ 01 ноября 2009

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

Как лучше всего перечислить все категории на странице с самыми новыми 20 фотографиями под каждой?

Сейчас я выбираю все фотографии, а затем сортирую их в PHP. Если в одной категории будет 500 фотографий, это будет очень неэффективно. Есть ли лучшие идеи для завершения SQL?

Единственный способ, о котором я подумал, - это зациклить 20 предельных запросов для каждой категории, но если есть 100 категорий, это кажется еще хуже!

псевдо-выход

[category_list] => {
    [0]=> {
        'category_title' => 'photos at sunset',
        'posts' => {
            [0] => {
                'photo_link' = '1.jpg',
            }
            [1] => {
                'photo_link' = '2.jpg',
            }
        }
    }
    [1]=> {
        'category_title' => 'photos at sunrise',
        'posts' => {
            [0] => {
                'photo_link' = '1.jpg',
            }
        }
    }
}

псевдокод

$query =  
"
SELECT 
    photographs.category_id, photographs.photo_link, categories.title
FROM 
     photographs
INNER JOIN 
     categories
ON 
     category.id = photographs.categories.id
ORDER BY
     category.id DESC
";

$result = $this->pdo->prepare($query);
$result->execute();

while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
    $post[] = $row;
}
$result = null;

$count = sizeof($post);
//get a list of the categories
for($i=0; $i < $count; $i++) { 
    $categories[$i] = $post[$i]['title'];
}
$categories = array_unique($categories);

//sort categories alphabetically
sort($categories);

//add the newest 20 photos to each category
$categories_count = count($categories);
$posts_count = count($post);
for($i=0; $i < $categories_count; $i++) { 
    $category_list[$i]['post_count'] = 0;
    for($k=0; $k < $posts_count; $k++) { 
        if ($categories[$i] == $post[$k]['category_title']) {
            if ($category_list[$i]['count'] == 19) {
                break;
            }
            $category_list[$i]['category_title'] = $post[$k]['category_title'];
            $category_list[$i]['post'][] = $post[$k];
            $category_list[$i]['post_count']++;
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 05 ноября 2009

Это можно сделать одним запросом.

Предполагая, что это схема таблицы:

CREATE TABLE `parkwhiz_demo`.`test` (
`photo_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`category_id` INT UNSIGNED NOT NULL ,
`date` DATETIME NOT NULL
) ENGINE = MYISAM ;

Вы можете получить упорядоченный список из 20 самых последних фотографий в категории по этому запросу:

select photo_id, category_id, date
from test
where (
   select count(*) from test as t
   where t.category_id = test.category_id and t.date >= test.date
) <= 20
order by category_id, date desc;

PHP-цикл для создания чего-то похожего на желаемую структуру массива:

$output = Array();
$prevRow = false;
$i=-1;
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
    if (!$prevRow || $row['category_id'] != $prevRow['category_id']) {
        $i++;
        $output[$i]['category_id'] = $row['category_id'];
        $output[$i]['posts'] = Array();
    }

    array_push($output[$i]['posts'], Array('image_id'=>$row['image_id']));
}
0 голосов
/ 01 ноября 2009

Просто предложение, но как насчет запуска одного запроса для списка категорий и использования результатов для создания запроса для элементов, используя комбинацию LIMIT и UNION? Таким образом, вы отправляете только два запроса; но возможно, что это не намного эффективнее, чем второй вариант, который вы описали, в зависимости от того, сколько накладных расходов требует каждый вызов базы данных и сколько оптимизации mySql сделает, когда увидит UNION (например, параллельная обработка оператора).

Я не знаю достаточно об этом, чтобы рекомендовать его, но я бы попробовал.

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