Android SQLite筛选RANK前1000行如何按CREATED_DATE去重留最新
解决思路
你当前的问题是GROUP BY分组时默认返回分组内的第一条记录,导致同rank下取到了更早创建的行,你可以通过以下两种方案实现需求:
方案1:窗口函数实现(适配Android 11及以上)
Android 11内置的SQLite版本为3.33.0,支持窗口函数,是最简洁的实现方式:
核心逻辑是对同rank的记录按创建日期倒序编号,只取每个分组编号为1的最新记录。
SQL语句如下:
SELECT id, rank, created_date FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY rank ORDER BY DATE(created_date) DESC) AS rn FROM 你的表名 WHERE rank BETWEEN 1 AND 1000 ) t WHERE rn = 1 ORDER BY rank ASC
对应的Android代码:
String sql = "SELECT id, " + RANK + ", " + CREATED_DATE + " FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY " + RANK + " ORDER BY DATE(" + CREATED_DATE + ") DESC) AS rn FROM " + DATABASE_TABLE + " WHERE " + RANK + " BETWEEN 1 AND 1000) t WHERE rn = 1 ORDER BY " + RANK + " ASC"; Cursor c = theDatabase.rawQuery(sql, null);
方案2:子查询关联实现(兼容所有Android版本)
如果需要兼容更低版本的Android,可以通过分组查询每个rank的最新日期,再关联原表拿到对应记录:
SQL语句如下:
SELECT t.id, t.rank, t.created_date FROM 你的表名 t INNER JOIN ( SELECT rank, MAX(DATE(created_date)) AS max_date FROM 你的表名 WHERE rank BETWEEN 1 AND 1000 GROUP BY rank ) tm ON t.rank = tm.rank AND DATE(t.created_date) = tm.max_date ORDER BY t.rank ASC
对应的Android代码:
String sql = "SELECT t.id, t." + RANK + ", t." + CREATED_DATE + " FROM " + DATABASE_TABLE + " t INNER JOIN (SELECT " + RANK + ", MAX(DATE(" + CREATED_DATE + ")) AS max_date FROM " + DATABASE_TABLE + " WHERE " + RANK + " BETWEEN 1 AND 1000 GROUP BY " + RANK + ") tm ON t." + RANK + " = tm." + RANK + " AND DATE(t." + CREATED_DATE + ") = tm.max_date ORDER BY t." + RANK + " ASC"; Cursor c = theDatabase.rawQuery(sql, null);
注意事项
- 如果你的
created_date字段存储的是毫秒时间戳,不需要加DATE()转换,直接排序即可,性能更高且不会出现日期格式解析错误。 - 如果同rank下存在多条完全相同创建日期的记录,可以在排序规则后追加
id DESC,优先返回id更大的记录,避免出现重复行。
内容的提问来源于stack exchange,提问作者Edmund Rojas
相关产品推荐
相关产品推荐

