Room数据库中基于Long类型日期查询金额总和的SQL语句问题
解决Room数据库日期范围查询金额总和的问题
首先得指出你当前查询语句的几个核心问题:
- 完全没必要用嵌套子查询,直接在外层
WHERE条件里过滤日期范围就可以了 - 同时查询
SUM(amount)、expense_id和Date逻辑混乱:SUM()是聚合函数,会返回符合条件数据集的金额总和,而expense_id和Date是单条记录的字段,没有配合GROUP BY的话,数据库会返回不确定的单条记录值,这和你要“总和”的需求不匹配 - 返回类型用
List<Expense>也不对,Expense实体对应单条消费记录,而聚合查询的结果是总和值(或分组后的总和列表),两者结构不匹配
场景1:查询日期范围内的总金额(单个数值)
如果你的需求是获取from到to之间所有消费的金额总和,应该用下面的查询:
// 如果amount是Long类型返回Long;如果是Double类型就返回Double @Query("SELECT SUM(amount) FROM EXPENSE WHERE Date BETWEEN :from AND :to") fun getTotalAmountBetweenDates(from: Long, to: Long): Long?
返回Long?是考虑到日期范围内没有记录时,SUM()会返回null,你可以根据业务需求调整是否允许空值。
场景2:按维度分组查询总和(比如按expense_id分组)
如果你需要按某个维度(比如消费类型ID expense_id)分别统计每个维度在日期范围内的金额总和,就需要配合GROUP BY,同时要创建一个专门的数据类来接收分组结果:
第一步:创建结果接收类
data class ExpenseSumResult( val expense_id: Long, // 用@ColumnInfo映射SQL里的聚合列别名 @ColumnInfo(name = "total_amount") val totalAmount: Long )
第二步:编写查询语句
@Query("SELECT expense_id, SUM(amount) AS total_amount FROM EXPENSE WHERE Date BETWEEN :from AND :to GROUP BY expense_id") fun getAmountSumByExpenseIdBetweenDates(from: Long, to: Long): List<ExpenseSumResult>
为什么你的原语句不能正常工作?
你的原查询SELECT sum(amount), expense_id, Date FROM EXPENSE Where amount in (SELECT amount FROM Expense WHERE Date BETWEEN :from AND :to)逻辑上就有问题:
- 子查询是找出日期范围内所有记录的
amount值,然后外层查询找amount在这些值里的记录,这完全是绕弯路,直接过滤Date范围即可 - 没有
GROUP BY的情况下,聚合函数SUM(amount)和单条记录字段expense_id、Date一起查询,数据库无法确定返回哪条记录的expense_id和Date,同时返回的SUM(amount)也不是你想要的日期范围内的总和,逻辑完全错误
内容的提问来源于stack exchange,提问作者Rams Solanki
相关产品推荐
相关产品推荐

