Android Studio Room相同查询本地与设备/模拟器结果不一致
差异原因
- 核心问题是你的SQL写法不符合SQL标准,存在非确定性行为:你在多处
GROUP BY name的查询中,SELECT了未被聚合、也不在GROUP BY字段中的value列。SQLite旧版本允许这种非法语法,但返回的value是对应分组中遍历到的第一条记录,不同版本SQLite的遍历顺序、UNION操作后的行排列逻辑存在差异,直接导致结果不一致。 - 具体到你的场景:本地运行的SQLite 3.27.2做了优化,会优先取
GROUP BY前ORDER BY date_col DESC排序后的第一行记录,刚好符合你的预期;而安卓各版本内置的SQLite版本(API23对应3.8.10、API28对应3.22.0)均未实现该优化,GROUP BY时按数据存储顺序取第一条记录,NAME5分组中2021-06-01的记录存储顺序早于2021-06-28的记录,因此返回了0.35的错误结果。 - 额外隐患:你使用
UNION而非UNION ALL,会对两个子查询的结果做去重处理,若某name的最大、最小日期为同一天(比如只有一条记录),会被误删一条,虽然不是本次问题的诱因,但也属于逻辑缺陷。
正确实现方案
全版本兼容方案(适配所有安卓API级别)
写法完全符合SQL标准,所有版本SQLite执行结果一致:
SELECT t1.* FROM tbl t1 INNER JOIN ( SELECT name, MAX(date_col) as nearest_date FROM tbl WHERE date_col <= '2021-06-28' -- 替换为你的目标日期 GROUP BY name ) t2 ON t1.name = t2.name AND t1.date_col = t2.nearest_date
高版本SQLite优化方案(SQLite 3.25+,对应安卓API30+)
使用窗口函数写法更简洁,还可以灵活支持「找目标日期前后最近的记录」需求:
SELECT id, date_col, name, value FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY name ORDER BY ABS(JULIANDAY(date_col) - JULIANDAY('2021-06-28')) ASC ) as rn FROM tbl WHERE date_col <= '2021-06-28' -- 不需要限制只找早于等于的可以删除这行 ) t WHERE rn = 1
内容的提问来源于stack exchange,提问作者Ofek
相关产品推荐
相关产品推荐

