android 带有偏移量的 sqlite 查询没有 return 需要的行

android sqlite query with offset doesn't return desired rows

我正在使用以下代码获取通知列表(总行数为 21)

List<Notification> list = new ArrayList<Notification>();
Cursor c = _db.query(TABLE_NAME, COL_ALL, null, null, null, null, order, get_limitStr(offset));
if(c != null && c.moveToFirst())
{
    while(!c.isAfterLast())
    {
        Notification model = cursorToModel(c);
        if(model != null)
        {
            list.add(model);
        }
        c.moveToNext();
    }
    c.close();
}

并且为 offset = 0 生成的查询是

SELECT Id, Token, Title, Read, Message, Image, CreateDate, CreateDateFA FROM Notifications ORDER BY CreateDate DESC LIMIT 20,0

它按预期工作 returns 20 行,当我将偏移量增加 1(偏移量 = 1)时,它 returns 只有 1 行是正确的,但问题是当offset 大于 1 那么查询将是

SELECT Id, Token, Title, Read, Message, Image, CreateDate, CreateDateFA FROM Notifications ORDER BY CreateDate DESC LIMIT 20,2

我认为它应该跳过 20 * 2 行然后开始从那里获取行,我的想法或我的查询是错误的。我在这里做错了什么?谢谢

LIMIT 20,2

and I thought it supposed to skip 20 * 2 rows and then starts taking rows from there, which either my thought or my query is wrong.

LIMIT 20,2 跳过前 20 行,returns 最多跳过剩余的 2 行。与 LIMIT 2 OFFSET 20.

相同

甚至 documentation 也说这是违反直觉的:

Instead of a separate OFFSET clause, the LIMIT clause may specify two scalar expressions separated by a comma. In this case, the first expression is used as the OFFSET expression and the second as the LIMIT expression. This is counter-intuitive, as when using the OFFSET clause the second of the two expressions is the OFFSET and the first the LIMIT. This reversal of the offset and limit is intentional - it maximizes compatibility with other SQL database systems. However, to avoid confusion, programmers are strongly encouraged to use the form of the LIMIT clause that uses the "OFFSET" keyword and avoid using a LIMIT clause with a comma-separated offset.

如果您想实现页面大小为 20 的结果分页,请使用类似 OFFSET k*20 LIMIT 20 的内容,其中 k 是从零开始的页码。

您可以将 Cursor 内的偏移量用作 "offset,limit" 值:

   Cursor cursor = db.query(
            TABLE_NAME,
            new String[]{COLUMN_NAME_1, COLUMN_NAME_2, COLUMN_NAME_3},
            null,
            null,
            null,
            null,
            null,
            "6,1000");

在这个例子中,我选择了从第 7 行开始的所有行(我想不超过 1000 行)。这里 6 是您的偏移量,1000 是限制。

这里需要理解LIMIT <offset>, <count>LIMIT <count> OFFSET <offset>是等价的

例子:

A) 我们有一个 table,id 列有 4 个记录,值为 1 | 2 | 3 | 4 行各 4 个。

B) 如果执行 select * from TABLE_NAME: 它 return 按顺序 1 从 table 编辑所有记录 | 2 | 3 | 4 .

C) 如果我们需要total(e.g. limit) 1条记录并且它应该从offset索引2开始,那么使用

select * from TABLE_NAME limit 1 offset 2

这将return记录索引| 3 | 作为请求限制 = 1 & 偏移索引 = 2.

同样可以使用 select * from company limit 2, 1; 类似于@laalto 提到的方法来实现。

注意,这里2是offset & 1是limit(order reverse)。

由于Android SDK 没有提供单独的属性来设置偏移量,在这种情况下,SQLiteDatabase.query(..., limit) 的最后一个'limit' 属性可以用作limit 2, 1.