安卓SQLite查询 - 获取最新的10条记录

26

我有一个保存在我的安卓应用中的数据库,并想要检索最后插入到数据库中的10条消息。

当我使用以下代码时:

Select * from tblmessage DESC limit 10;

它给了我前10条消息, 但是从顶部开始. 但我想要最后10条消息. 这可行吗?

假设整个表的数据为 -

1,2,3,4,5....30

我写了查询语句 select * from tblmessage where timestamp desc limit 10

它显示的是 30,29,28...21

但我想要的顺序是 - 21,22,23...30


9
您需要使用ORDER BY子句更改查询,如下所示:SELECT * FROM tblmessage ORDER BY _id DESC LIMIT 10。此查询将按_id列降序排列,并仅返回最后10条消息记录。 - ρяσѕρєя K
我猜我的表格没有创建任何 _id 列。 - Darpan
@Durpan 如果它是一个SQLite数据库,那么它总是有一个rowid字段(除非你使用WITHOUT ROWID子句专门创建表)。rowid列始终被索引,因此也会提供快速的结果。 - Arthur Tacca
9个回答

41

将DESC改为ASC,即可获取所需的记录,但如果您需要按顺序排列,则需要反转它们的顺序。您可以在自己的代码中执行此操作,也可以像这样扩展查询:

select * from (
    select *
    from tblmessage
    order by sortfield ASC
    limit 10
) order by sortfield DESC;

你确实应该总是指定一个order by子句,而不仅仅是ASC或DESC。


我想要逆转它们的顺序。我怎么做呢? - Gaurav Arora
1
假设整个表的数据如下 - 1,2,3,4,5....30 我编写了查询语句 select * from tblmessage where timestamp desc limit 10 它显示的是 30,29,28...21 但是我希望序列是 - 21,22,23...30我该如何得到相同的结果 - Gaurav Arora
1
太棒了!我不知道你可以像这样嵌套选择。 - Matt Logan
1
请参考 @moodboom 的回答以获得正确的排序。 - NuSkooler
应该选择SELECT ASC FROM DESC,而不是DESC FROM ASC。升序会给你1、2、3、4、5、6...,而降序会给你30、29、28、27...所以首先选择降序,即最高值的那些,然后选择所有内容并翻转排序顺序。 - user3342816
需要注意的一个关键点是,如果您在排序字段上创建索引,此查询才能快速运行。如果您习惯于使用SQL数据库,则这一点很明显,但对于所有读者来说可能并不明显。如果您只想要数据库内部顺序,可以在ORDER BY子句中指定rowid字段(它始终被索引,因此您无需自己创建索引)。 - Arthur Tacca

28

在大型数据库中,ORDER BY DESC语句可能会导致系统变慢,例如树莓派。一个不错的方法是使用OFFSET命令来避免使用ORDER BY,同时还能保持存储的顺序:

SELECT * FROM mytable LIMIT 10 OFFSET (SELECT COUNT(*) FROM mytable)-10;

查看:http://www.sqlite.org/lang_select.html

使用以下内容检查您的性能:

.timer ON

这里有一个机会,偏移量可能会变为负数,从而引发异常。 - Atul
当然,您可以调用上下边界的值。但是SQLite不会抛出异常,而是返回所有可能的值。 - McPeppr
我使用了这个选项,它按照我的要求工作。即使是负值,它仍然安全。 - Erdi İzgi
这并不是普适的!如果没有 ORDER BY,结果将以任意顺序返回。如果您使用带有索引的 WHERE 子句,则 SQLite 将根据其内部索引查找返回不同的数据子集。 - ge0rg
这个解决方案要快得多,而且即使表格中的行数比您尝试获取的最大限制要少,它也可以工作。这很好,因为如果行数较少,您只会获取表格中的所有行。 - RaduS
这个答案比其他答案要糟糕得多:当使用 OFFSET 时,SQLite 必须遍历所有中间行,对于大表来说速度会非常慢。对于 COUNT 也是如此,因此这个查询的速度是双倍慢!使用顶部答案中的嵌套 ASC / DESC 查询将更快,只要(a)您指定了一个 ORDER BY 列,否则您的行可能以随机顺序返回,而且(b)在 ORDER BY 中的列被索引,如果您按 rowid 排序,它总是被索引的。 - Arthur Tacca

9
略微改进的答案:
select * from (select * from tblmessage order by sortfield DESC limit 10) order by sortfield ASC;

迈克尔·迪龙(Michael Dillon)在他的回答中提出了正确的想法,但是该示例给出了前几行,颠倒顺序:
select * ... (select * ... ASC limit 10) ... DESC

他想要最后一个,应该是:
select * ... (select * ... DESC limit 10) ... ASC

是的 - 选择 * ... (选择 * ... DESC 限制 10) ... ASC - Tigran Sarkisian

1

试试这个,

SQLiteDatabase database = getReadableDatabase();
Cursor c=database.rawQuery("sql Query", null);
if(c.moveToFirst) {
    int curSize=c.getCount()  // return no of rows
    if(curSize>10) {
       int lastTenValue=curSize -10;
       for(int i=0;i<lastTenValue;i++){
          c.moveToNext();
       }
    } else {
       c.moveToFirst();
    }
}

然后检索最近的10条数据。


1
如果您的表包含一个自增的主键列(例如某个“row_id”),那么您只需要按照此列的DESC顺序进行单次选择即可。
原始请求如下:
select * from table_name order by row_id DESC limit 10

Android实现是:

private Cursor queryLastEvents() {
    return getDatabase().query("table_name", null, null, null, null, null, "row_id DESC", "10");
}

这将会给出最后10条记录,但是是以相反的顺序。 - Atul

1
 "SELECT *  FROM( SELECT *  FROM " + tablename + whereClause + " ORDER BY timestamp DESC LIMIT 10)  ORDER BY timestamp ASC";

0
cursor.moveToLast();
while (cursor.moveToPrevious()){
       //do something
}

使用相同的查询:选择*从tblmessage中按时间戳降序排列限制10条


一些关于为什么这是正确答案的评论可能会帮助提问者。 - joanolo
我在一个聊天应用程序中也遇到了同样类型的问题,但是我通过执行cursor.moveToLast();来解决了它; while (cursor.moveToPrevious()){ //做一些事情 } - Mąñîşh Şhârmá Mkş

0
select * from
(select * from table_name order by yourfield ASC limit 10)
order by yourfield DESC;

没有比这更好的解决方案。


0
在您的查询中,DESC 被解释为表别名。
正如 ρяσѕρєя K 所提到的,要能够指定排序方向,您需要首先使用 ORDER BY 子句进行排序。
要排序的列应该是一个时间戳,如果您有一个,或者是一个自增列,比如表的主键。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接