Несколько сложный запрос mysql

В настоящее время я работаю над веб-сайтом базы данных новостей, и я не могу создать запрос для выбора 5 самых горячих новостных статей. 2 таблицы базы данных, на которые влияет этот запрос:

  • Новости - содержит все новости (идентификатор, автор, сообщение и т. д.)
  • Rates — содержит все рейтинги новостей (id, news_id, рейтинг и т. д.)

Теперь мой запрос должен выбрать 5 news_ids из таблицы Rates с самым высоким средним рейтингом и наибольшим количеством голосов (так что: упорядочено по AVG (Rating) и COUNT (*), как я полагал). Сначала я попытался сделать так, чтобы мой запрос также мгновенно получал всю информацию об этих news_ids из таблицы новостей (используя предложение WHERE id IN (- запрос, выбирающий 5 самых горячих news_ids--)), но это вернуло ошибку моей версии MySql. невозможность использования LIMIT внутри подзапроса предложения WHERE IN.

Что ж, надеюсь, вы поможете мне с первым запросом, который должен выбрать эти 5 news_id. Запрос, который я получил на данный момент (но не полностью рабочий):

SELECT news_id FROM 
              (SELECT news_id, AVG(rating) AS average_r, COUNT(*) AS amt_r 
                      FROM rates 
                      GROUP BY news_id 
                      ORDER BY average_r,amt_r 
                      DESC LIMIT 5
               ) AS news_rates

или в содержании остальной части моего сценария:

$get_hot_news_ids = mysql_query("SELECT news_id FROM 
        (SELECT news_id, AVG(rating) AS average_r, COUNT(*) AS amt_r 
         FROM rates 
         GROUP BY news_id 
         ORDER BY average_r,amt_r DESC LIMIT 5) AS news_rates");

    $first = 1;
    while($news_id     = mysql_fetch_assoc($get_hot_news_ids)) {
        if(!$first) {
            $hot_news_ids .= " ,";
        }else{
            $first = 0;
        }
        $hot_news_ids .= $news_id['news_id'];
    }
    //print_r($hot_news_ids);
    $get_hot_news = mysql_query("SELECT * FROM news 
        WHERE id IN($hot_news_ids) 
        ORDER BY FIELD(id, $hot_news_ids)");

person Skyfe    schedule 06.03.2011    source источник


Ответы (3)


Вы уверены, что оба значения medium_r и amt_r расположены в порядке убывания?

SELECT news_id FROM 
              (SELECT news_id, AVG(rating) AS average_r, COUNT(*) AS amt_r 
                      FROM rates 
                      GROUP BY news_id 
                      ORDER BY average_r DESC, amt_r DESC
                      LIMIT 5
               ) AS news_rates
person PPC-Coder    schedule 06.03.2011
comment
Это просто исправлено! Такая глупая ошибка, большое спасибо, теперь все работает :). - person Skyfe; 06.03.2011

Попробуй это:

SELECT TOP 5 N.id, N.author, N.message, AVG(R.rating) AS rate, COUNT(R.news_id) AS votes
FROM       news  N
INNER JOIN rates R ON N.id = R.news_id
GROUP BY N.id, N.author, N.message
ORDER BY rate, votes
person MestreLion    schedule 06.03.2011
comment
MySql не поддерживает предложение TOP n. - person The Scrum Meister; 06.03.2011
comment
Это похоже на MS-SQL, я не думаю, что у mysql есть SELECT TOP. - person PPC-Coder; 06.03.2011
comment
Спасибо за ответ. Предоставленный вами запрос MySql дает мне mysql_error: у вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с «5 N.id, N.author, N.message, AVG (R.rating) AS rate, COUNT (R.news_id) AS голосов F» в строке 1. - person Skyfe; 06.03.2011
comment
Вау, не так ли?? Даже в версии 5.xx? Я сделал несколько (небольших) проектов с использованием MySQL, трудно поверить, что до сих пор мне никогда не понадобилось предложение TOP n, только чтобы узнать, что оно не поддерживается (пока?). - person MestreLion; 06.03.2011
comment
@PPC-Coder: это не ориентировано на MS-SQL ... оно также работает в Oracle. На самом деле, это работает (почти) во всех СУБД, с которыми я работал до сих пор. Я очень удивлен, что такая зрелая база данных, как MySQL, не поддерживает ее. - person MestreLion; 06.03.2011
comment
@Skyfe: неважно, ошибка связана с предложением TOP n в моем SELECT. если MySQL не поддерживает TOP, выберите решение Scrum Meister. - person MestreLion; 06.03.2011

Вместо этого вы можете использовать объединение, что позволит limit:

SELECT *
FROM news n JOIN (
    SELECT news_id, AVG(rating) AS average_r, COUNT(*) AS amt_r 
    FROM rates 
    GROUP BY news_id 
    ORDER BY average_r,amt_r DESC 
    LIMIT 5
  ) top5 ON n.news_id = top5.news_id
ORDER BY top5.average_r,top5.amt_r 

Примечание. Возможно, вы захотите изменить свой запрос на ORDER BY average_r DESC, amt_r DESC, чтобы получить элементы с самой высокой оценкой, а не с самой низкой оценкой.

person The Scrum Meister    schedule 06.03.2011
comment
Большое спасибо, однако PPC-Coder уже дал базовое решение, я все еще ценю объяснение и альтернативный запрос с использованием соединения (не совсем понял соединение). - person Skyfe; 06.03.2011