【问题标题】:android sqlite query with offset doesn't return desired rows带有偏移量的android sqlite查询不返回所需的行
【发布时间】:2015-08-08 03:27:46
【问题描述】:

我正在使用以下代码获取通知列表(总行数为 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

它按预期工作并返回 20 行,当我将偏移量增加 1(偏移量 = 1)时,它只返回 1 行,这是正确的,但问题是当偏移量大于 1 时,查询将是

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

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

【问题讨论】:

标签: java android sqlite android-sqlite


【解决方案1】:
LIMIT 20,2

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

LIMIT 20,2 跳过前 20 行,最多返回剩余 2 行。和LIMIT 2 OFFSET 20一样。

即使是documentation 也说它违反直觉:

LIMIT 子句可以指定两个用逗号分隔的标量表达式,而不是单独的 OFFSET 子句。在这种情况下,第一个表达式用作 OFFSET 表达式,第二个表达式用作 LIMIT 表达式。这是违反直觉的,因为当使用 OFFSET 子句时,两个表达式中的第二个是 OFFSET,第一个是 LIMIT。这种偏移量和限制的反转是有意的——它最大限度地提高了与其他 SQL 数据库系统的兼容性。但是,为避免混淆,强烈建议程序员使用使用“OFFSET”关键字的 LIMIT 子句形式,并避免使用带有逗号分隔偏移量的 LIMIT 子句。

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

【讨论】:

  • 是的,我再次阅读后意识到这一点。非常感谢,我马上试试
【解决方案2】:

您可以使用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 是限制。

【讨论】:

    【解决方案3】:

    这里需要明白LIMIT &lt;offset&gt;, &lt;count&gt;LIMIT &lt;count&gt; OFFSET &lt;offset&gt;是等价的。

    一个例子:

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

    B) 如果执行select * from TABLE_NAME:,它会按顺序从表中返回所有记录 1 | 2 | 3 | 4.

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

    select * from TABLE_NAME limit 1 offset 2

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

    使用@laalto 提到的select * from company limit 2, 1; 也可以达到同样的效果。

    注意,这里 2 是偏移量,1 是限制(逆序)。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-29
      • 2017-03-27
      • 1970-01-01
      • 2019-04-07
      • 1970-01-01
      • 2014-09-27
      • 1970-01-01
      • 2017-11-30
      相关资源
      最近更新 更多