【发布时间】:2018-05-06 11:34:58
【问题描述】:
作为实现 GraphQL API 的一部分,我尝试在分页之前/之后提供。例如,返回 具有给定 ID 的记录之后的 LIMIT 记录。这必须适用于已经存在任意 JOIN、WHERE 和 ORDER BY 子句的任意 SELECT 语句。
与仅使用页码相比,这种分页的好处是,当基础数据发生变化时,它可以更接近地返回预期的结果页面。
如果我可以在 after 使用它,我也可以通过反转 ORDER BY 子句使其在 before 使用,所以这里我将只关注 before em>在条件之后。
修改给定 SELECT 语句以完成此操作的最简单或最有效的方法是什么?
我的第一个想法是在 WHERE 子句中添加一个 AND 条件,将结果限制为那些来自 ORDER BY 子句的列值大于或等于它们在具有给定 ID 的记录中的值的结果。但这似乎不起作用,因为 ORDER BY 子句列中没有唯一性的期望,因此无法知道目标记录将落在结果中的哪个位置,因此无法知道如何设置 LIMIT返回正确数量的记录。
另一种方法是首先在初始 SELECT 语句中发现目标记录的偏移量,然后将 LIMIT offset+1, limit 子句添加到具有发现的偏移量的初始 SELECT 语句。
MySQL 没有row_count() 或类似功能,但可以添加行号like this:
SELECT @rownum:=@rownum+1 ‘rank’, t.*
FROM my_table t, (SELECT @rownum:=0) r ORDER BY field2;
那么上面可以作为子查询来获取目标记录的排名,例如
SELECT rank FROM (SELECT @rownum...) WHERE id = 42
然后使用该排名作为最终查询的偏移量:
SELECT ... LIMIT (rank + 1), 100
这可以作为具有多个子查询的单个查询来完成,例如
SELECT ... LIMIT (SELECT rank from (SELECT @rownum...) ...) + 1, 100
但是这三个查询方法似乎是一种复杂且不是非常快速的方法来执行一个非常频繁使用的操作,这给我们的数据库服务器带来了比我们希望的更高的负载。
有没有更好的方法来做到这一点?
编辑:要求提供特定示例。假设我想从包含 10 篇文章的表格中获取包含 2 篇文章的页面。我们将对这个查询进行分页:
select id, title from articles order by title desc
桌子:
id, title
1, "a"
3, "b"
4, "c"
6, "d"
7, "e"
8, "f"
9, "g"
10, "h"
11, "i"
12, "k"
因此,当请求页面之后 id 6 时,正确的记录将是4, "c" 和3, "b"。这需要适用于任意 WHERE 和 ORDER BY 子句。
【问题讨论】:
-
获取最后显示的item的ID,然后取后面的25行?
-
@Andomar,问题是,对于任意排序的 SELECT 语句,我如何“获取之后的 25 行”?
-
解决的关键是你所说的"after"。您是指具有较晚日期、较高主键等的行吗?通过创建一个选择该行作为“锚点”(IOW,所需行之后的行)并加入该子查询的子查询,您可以使用 order by 来获取之后的行。
-
好吧,如果我理解正确的话,我会使用“rank”进行查询,并且在 where 部分中存在相同的“rank 查询”。我不知道我是否足够清楚。您能否添加一些示例数据以及之后和之前的结果?
-
如果是简单的分页问题,那么只需使用 LIMIT startval,numrow 语法重复上一个查询
标签: mysql sql pagination