如何用单条带分页的SQL查询获取3条历史记录与7条即将发生的记录
问题描述
我有如下结构的event表:
| id | event | date_time |
|---|---|---|
| 1 | event1 | 2023-02-28 |
| 2 | event2 | 2023-03-01 |
| 3 | event3 | 2023-03-05 |
| 4 | event4 | 2023-03-10 |
| 5 | event5 | 2023-03-29 |
| 6 | event6 | 2023-03-31 |
| 7 | event7 | 2023-04-01 |
| 8 | event8 | 2023-04-05 |
| 9 | event9 | 2023-04-06 |
| 10 | event10 | 2023-04-10 |
| 11 | event11 | 2023-05-01 |
目前我通过两个独立查询实现需求(以当前日期为2023-03-29为例):
Q1:获取3条发生在当前日期之前的事件(按日期升序)
SELECT * FROM event WHERE date_time < CURDATE() ORDER BY date_time ASC LIMIT 3;
Q2:获取7条发生在当前日期及之后的事件(按日期升序)
SELECT * FROM event WHERE date_time >= CURDATE() ORDER BY date_time ASC LIMIT 7;
想请教是否可以将这两个查询合并为一条带分页的查询?要求每页显示10条记录。
解决方案
当然可以把这两个查询合并成一条带分页的语句,下面提供两种符合需求的实现方式:
方式一:严格保留原3条历史+7条当前/未来的分页逻辑
如果需要每页固定最多显示3条历史事件、7条当前及未来事件,用下面的查询:
-- 先取3条历史事件,标记排序优先级为1 (SELECT *, 1 AS sort_priority FROM event WHERE date_time < CURDATE() ORDER BY date_time ASC LIMIT 3) UNION ALL -- 再取7条当前及未来事件,标记排序优先级为2 (SELECT *, 2 AS sort_priority FROM event WHERE date_time >= CURDATE() ORDER BY date_time ASC LIMIT 7) -- 整体按优先级排序,同优先级内按日期升序 ORDER BY sort_priority, date_time ASC -- 分页控制:LIMIT 每页数量 OFFSET 偏移量(第一页OFFSET 0,第二页OFFSET 10) LIMIT 10 OFFSET 0;
- 用
sort_priority字段保证历史事件始终排在当前/未来事件前面,子查询的LIMIT分别控制两类事件的数量,外层的LIMIT + OFFSET实现分页。
方式二:通用时间顺序分页
如果不需要严格限制两类事件的数量,只是想按「历史事件从早到晚,接着当前/未来事件从早到晚」的顺序分页,每页10条,可以简化成:
SELECT * FROM event ORDER BY -- 先区分历史和当前/未来事件,历史事件排前面 CASE WHEN date_time < CURDATE() THEN 1 ELSE 2 END, -- 同类别内按日期升序排列 date_time ASC -- 分页参数:OFFSET根据页码调整,比如第N页就是OFFSET (N-1)*10 LIMIT 10 OFFSET 0;
性能提示
如果event表数据量较大,建议给date_time字段建立索引,这样排序和条件查询的效率会高很多。如果date_time包含时间部分,需要根据实际业务调整条件(比如用DATE(date_time) < CURDATE()来忽略时间只比较日期)。
内容的提问来源于stack exchange,提问作者Kishan Chauhan
相关产品推荐
相关产品推荐

