确定记录在哪一页

问题描述 投票:0回答:1

如何判断某条记录在哪个页面?

假设我使用如下查询每页显示 5 条记录:

SELECT * FROM posts ORDER BY date DESC LIMIT 0,5
SELECT * FROM posts ORDER BY date DESC LIMIT 5,5
SELECT * FROM posts ORDER BY date DESC LIMIT 10,5

样本数据:

id  | name | date
-----------------------------------------------------
1   | a    | 2013-11-07 08:19               page 1
2   | b    | 2013-12-02 12:32
3   | c    | 2013-12-14 14:11
4   | d    | 2013-12-21 09:26
5   | e    | 2013-12-22 18:52      _________ 
6   | f    | 2014-01-04 11:20               page 2
7   | g    | 2014-01-07 21:09
8   | h    | 2014-01-08 13:39
9   | i    | 2014-01-08 16:41
10  | j    | 2014-01-09 07:45      _________
11  | k    | 2014-01-14 22:05               page 3
12  | l    | 2014-01-21 17:21

有人可能会编辑一条记录,比如使用

id = 7
,或者插入一条新记录 (
id = 13
)。如何确定该记录位于哪一页?原因是我想显示包含刚刚编辑或添加的记录的页面。

好吧,我想如果记录被编辑,我可以只显示相同的页面。但问题是当添加一条记录时。该列表可以按名称排序,新记录可以放置在任何地方:(

有什么方法可以执行类似

SELECT offset WHERE id = 13 ORDER BY date LIMIT 5
的查询并返回 10 吗?

sql sqlite select pagination offset
1个回答
1
投票

为了这个例子,我们假设条目

7
刚刚被添加(并且可能有重复的名称) - 您需要做的第一件事是找到在该条目之前有多少条目(基于
name 
),因此:

SELECT COUNT(*) 
FROM Posts
WHERE name <= 'g'
      AND id < 7

这里,

id
被用作“决胜局”列,以确保稳定的排序。它还假设我们也知道
id
的值 - 鉴于非关键数据可以重复,您需要这种功能。
无论如何,这都会为我们提供这一行之前的行数 (6)。通过一些整数除法运算(基于
LIMIT
),我们现在可以获得相关信息:

(int) ((6 - 1) / 5) = 1

...不过,这是针对 0 索引页面的(即,条目 1 - 5 出现在页面“0”上);然而,在这种情况下,它对我们有利。请注意,我们必须从初始计数中减去 1,因为第一个是 1,而不是 0 - 否则,条目 5 将出现在第二页,而不是第一页。 我们现在有了 page
索引,但我们需要将其转换为 entry 索引。一些简单的乘法就可以为我们做到这一点: (1 * 5) + 1 = 6

(忽略这与计数相同 - 在本例中这是巧合)。
这为我们提供了页面上第一个条目的索引,即

OFFSET
的值。

我们现在可以编写查询:

SELECT id, name, date FROM Posts ORDER BY name, id LIMIT 5 OFFSET 6

(请记住,如果我们假设 
id

可能是重复的,我们需要

name
来保证数据的稳定排序!)。
这是两次数据库访问。令人惊讶的是,SQLite 允许 
LIMIT
/
OFFSET
值成为 SQL 子查询的结果(请记住,并非所有 RDBMS 都允许它们成为
主机变量
,这意味着只能使用动态 SQL 进行更改。尽管在 at至少有一种情况,数据库有 ROW_NUMBER() 来弥补......)。不过,我无法摆脱子查询的重复。
SELECT Posts.id, Posts.name, Posts.date, Pages.pageCount
FROM Posts
CROSS JOIN (SELECT ((COUNT(*) - 1) / 5) + 1 as pageCount 
      FROM Posts
      WHERE name <= 'g'
            AND id < 7) Pages
ORDER BY name, id
LIMIT 5, (SELECT ((COUNT(*) - 1) / 5) * 5 + 1 as entryCount 
      FROM Posts
      WHERE name <= 'g'
            AND id < 7);

(以及工作中的 
SQL Fiddle 示例

)。

© www.soinside.com 2019 - 2024. All rights reserved.