基于两列排序mysql查询

Posted

技术标签:

【中文标题】基于两列排序mysql查询【英文标题】:order mysql query based on two columns 【发布时间】:2021-09-23 18:14:41 【问题描述】:

为了让我的查询更快,我根据设置为起始值的主键idpaginate,即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 DESCid 将不是连续的,因此如果我请求更多帖子,结果将重复第一组结果。

谁能帮我写一个查询来获取帖子和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);

【问题讨论】:

使用 INNER JOIN 代替逗号 你是什么意思 代替FROM a,b WHERE a.x=b.x,使用FROM a JOIN b ON a.x=b.x。它们具有相同的效果;后者是“现代”语法。 是的,谢谢@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 条结果,并从第 16 条开始设置(下次使用)$leftoff_likes 和 $leftoff_id。通过 [Next][Prev] 按钮后面的 URL 传递它们。

OFFSET 从未使用过。

如果可行,请INDEX(likes, id)

(这个小费在http://mysql.rjweb.org/doc.php/deletebig#iterating_through_a_compound_key 中被隐藏了)

杂记:

“记住你离开的地方”比使用LIMITOFFSET 更好。见:http://mysql.rjweb.org/doc.php/pagination

这会带来多项更改。我建议编写两个完整的查询,而不是使用$offset 进行修补。

【讨论】:

谢谢,请您使用我上面的代码进一步解释一下。 啊,我跳过了一些东西——$start 还不够,你还需要记住$likes。用 $likes 和 $start 替换 $Genus 和 $species。 对我来说$likes 不是变量,我应该用posts.likes 代替吗?我很难将它们关联起来。 @MaxNjoroge - 完成一页后,您有两个数字表示页面“离开”的位置——为页面提取的“最后”行的likesid。这些来自SELECT 进入PHP 变量,然后进入[Next] 或[Prev] 按钮的URL,并返回PHP 毛皮使用$likes 和$id 用于下一页的SELECT。请参阅我的分页博客。 (建议取 16 行并记住第 16 行的 likesid;这会将 '>' 更改为 '>=' 等) 谢谢@RickJames 和@Luuk,结果@RickJames 代码工作得很好。 @Luuk,它不起作用,因为我的查询嵌套在 $db-&gt;query() 中,带有间距和换行符,不起作用。但除此之外,@RickJames 代码运行良好。谢谢@Luuk 的小提琴让我看到了这个!

以上是关于基于两列排序mysql查询的主要内容,如果未能解决你的问题,请参考以下文章

MySQL查询订购两列,一个ASC另一个DESC

为啥我在这个非常简单的 MySQL 查询上得到文件排序?

Mysql查询根据两列动态将行转换为列

MySQL - 在一个查询中按两列计数[重复]

MySQL分组、排序

MySQL 子查询出错