заказ запроса mysql на основе двух столбцов

#php #mysql #sql

Вопрос:

Чтобы ускорить мой запрос, я paginate в соответствии с первичным ключом id , который установлен в качестве начального значения, т. е. posts.id > $start

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

 // start value
$start = $_GET['start'];

if ($start <= 0) {
    // set as first request
    $offSet = "AND posts.id > $start";
}
else if ($start > 0) {
    // set as subsequent request
    $offSet = "AND posts.id < $start";
}

// fetch posts
$posts = $db->query("SELECT posts.id, posts.likes,
                        posts.dislikes, posts.comments
    FROM posts, users
    WHERE posts.user_id=users.id
        $offSet
    ORDER BY posts.id DESC LIMIT 0, 15"); 

Вот как я выбираю наиболее понравившиеся посты

 // fetch posts
$posts = $db->query("SELECT posts.id, posts.likes,
                        posts.dislikes, posts.comments
    FROM posts, users
    WHERE posts.user_id=users.id
        $offSet
      AND posts.likes != 0
    ORDER BY posts.likes DESC LIMIT 0, 15"); 

Проблема в том , что если я ORDER BY likes DESC , id то не буду последовательным, и, следовательно, если я запрошу больше сообщений, результаты повторят первый набор результатов.

Может ли кто-нибудь помочь мне написать запрос, который будет получать сообщения ORDER BY posts.likes DESC и при этом позволит мне разбивать запрос на страницы на основе id , чтобы последующие запросы постепенно не замедлялись (из-за того, что mysql просматривает все предыдущие строки)

Это реализация, любезно предоставленная @RickJames

 $start = $leftoff_likes = 0;

// fetch most liked posts
$posts = $db->query("
    SELECT posts.id, posts.body, posts.user_id, posts.tag, posts.date, posts.comments, posts.likes, posts.dislikes, users.name, users.image 
    FROM posts, users 
    WHERE   posts.likes <= $leftoff_likes
      AND ( posts.likes <  $leftoff_likes OR posts.id < $start ) 
      AND posts.user_id=users.id 
    ORDER BY posts.likes DESC, posts.id DESC 
    LIMIT 0, 15");

echo json_encode($posts); 

Комментарии:

1. Используйте ВНУТРЕННЕЕ СОЕДИНЕНИЕ вместо запятой

2. Что вы имеете в виду

3. Вместо FROM a,b WHERE a.x=b.x того , чтобы делать FROM a JOIN b ON a.x=b.x . Они имеют один и тот же эффект; последний является «современным» синтаксисом.

4. да, спасибо @RickJames, это действительно хорошо работает!

Ответ №1:

Эффективное соединение:

Вам нужно 2 столбца ORDER BY , чтобы лучше оформить заказ. И это усложняет WHERE предложение, особенно когда несколько пунктов имеют одинаковое количество лайков.

Начиная с наиболее понравившихся:

 SELECT ...
    WHERE   likes <= $leftoff_likes
      AND ( likes <  $leftoff_likes OR id < $leftoff_id ) 
    ORDER BY likes DESC, id DESC
    LIMIT 16
 

Начиная с наименее понравившегося:

 SELECT ...
    WHERE   likes >= $leftoff_likes
      AND ( likes >  $leftoff_likes OR id > $leftoff_id ) 
    ORDER BY likes ASC, id ASC
    LIMIT 16
 

Отобразите первые 15 результатов на текущей странице и установите (для следующего раза) $leftoff_likes и $leftoff_id из 16-го элемента. Передайте их по URL [Next] -адресу за кнопками [Prev] и.

OFFSET никогда не используется.

Есть, если это практически, INDEX(likes, id)

(Этот наконечник был спрятан в http://mysql.rjweb.org/doc.php/deletebig#iterating_through_a_compound_key )

Примечания к сборнику:

«Вспоминать, на чем вы остановились» лучше, чем использовать LIMIT с OFFSET . См.: http://mysql.rjweb.org/doc.php/pagination

Это приводит к многочисленным изменениям. Я рекомендую написать два полных запроса вместо исправления с $offset помощью .

Комментарии:

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

2. Ах, я кое-что пропустил $start -этого недостаточно, вам тоже нужно помнить $likes . Замените $Род и $вид на $нравится и $начало.

3. для меня $лайки не являются переменной величиной, я должен заменить их постами. нравится? Мне немного трудно сопоставить их.

4. @MaxNjoroge — Когда вы заканчиваете с одной страницей, у вас есть два числа, обозначающие, где страница «остановилась» — likes и id «последней» строки, выбранной для страницы. Они поступают из переменных SELECT into PHP, затем в URL-адрес для кнопки [Далее] или [Предыдущая] и обратно в PHP, чтобы использовать их как $likes и $id для следующей страницы SELECT . Смотрите мой блог о разбиении на страницы. (Он рекомендует выбрать 16 строк и запомнить likes и id из 16-го; это изменяет » > » на «> > = » и т. Д.)

5. Спасибо @RickJames и @Luuk, оказывается, код @RickJames работает просто отлично. @Luuk, Это не сработало, потому что мой запрос был вложен, в $db->query() который с интервалом и новой строкой не работал. Но в остальном код @RickJames работает просто отлично. Спасибо @Luuk за вашу скрипку, которая заставила меня это увидеть!