需求
在新闻详情页面显示上一篇新闻和下一篇新闻.
有以下要求
- 不能全表扫描
- 上一篇和下一篇会受到排序条件(还可能是多个)的影响.
继续往下看, 你会发现这个问题并没想象中简单.
假设数据库中数据如下
id | read_count | created_at |
---|---|---|
1 | 100 | 1566138753 |
2 | 100 | 1566138754 |
3 | 99 | 1566138753 |
4 | 99 | 1566138754 |
现在新闻列表根据需求排序: 阅读数量多的在前, 发布时间最新的在前, Sql如下:
SELECT * FROM t ORDER BY read_count DESC, created_at DESC
得到的结果排序如下:
[2 , 1 , 4 , 3]
假如想要得到文章4的上一篇下一篇 你会怎么写Sql?
对于上一篇你可以会这样写: SELECT * FROM t WHERE read_count> 99 AND created_at > 1566138754 LIMIT 0,1 ORDER BY read_count, create_at
你会发现得不到任何数据. 那换成>=
呢? 也不对, 得到的是2, 而不是1.
当然获取下一篇文章也有相同的问题.
那怎么办呢?
正确方法很简单:模拟mysql的排序过程
mysql的排序是有优先级的,如ORDER BY read_count, created_at
, 当read_count相同时才会根据created_at排序, 所有就会有两个分支: read_count相同和read_count不同, 也正是因为这样我们才无法一行SQL就能得到正确结果.
我们可以模拟这个排序过程:
上一条:
先执行WHERE create_count=99 AND created_at > 1566138754 ORDER BY created_at
, 会发现取不到任何数据,
那么就需要进入第二个分支: WHERE create_count>99 ORDER BY create_count
, 这时就会得到 1.
下一条:
同样的道理, 在第一个分支
WHERE create_count=99 AND created_at < 1566138754 ORDER BY created_at DESC
便能得到正确结果: 3.
就这样啦.
网友评论