Android Room DAO中如何为日志条目计数设置条件限制?
解决Android Room中锻炼完成率计数超标的问题
我来帮你搞定这个问题——核心就是要给每个动作(对应junction_id)的日志条目加上数量限制,只取前3条来计数,这样就不会因为用户多记了条目导致完成率超过100%了。
修改思路
原查询的entries CTE是直接统计所有符合条件的日志总数,没有按动作分组做数量限制。我们需要调整这部分逻辑:
- 按
junction_id(每个动作的唯一标识)对日志条目分组; - 给每个组内的日志条目编号(比如按日志ID或日期排序);
- 只保留每个组内编号≤3的条目,再统计这些条目的总数,作为修正后的"已完成组数"。
修改后的完整查询
@Query(""" WITH limited_log_entries AS ( SELECT l.log_id, l.junction_id, -- 按动作分组,给每个组内的日志编号,这里按log_id升序取最早的3条,可按需改为date排序 ROW_NUMBER() OVER (PARTITION BY l.junction_id ORDER BY l.log_id) AS row_num FROM log_entries_table AS l LEFT JOIN exercise_workout_junction_table AS e ON e.exercise_workout_id = l.junction_id WHERE l.date IN (:dates) AND e.workout_id = :workoutID ), entries AS ( SELECT COUNT(log_id) AS log_entry_count FROM limited_log_entries WHERE row_num <= 3 -- 只保留每个动作的前3条日志 ), sets AS ( SELECT sum(set_number) AS set_sum FROM exercise_workout_goals_table AS eg LEFT JOIN exercise_workout_junction_table ej ON ej.exercise_workout_id = eg.junction_id WHERE ej.workout_id = :workoutID ) SELECT ((SELECT log_entry_count FROM entries) * 100.0 / (SELECT set_sum FROM sets)) AS workout_completion_pct """) LiveData<String> getWorkoutCompletionPercentage(int workoutID, List<String> dates);
关键调整说明
新增
limited_log_entriesCTE:- 使用
ROW_NUMBER() OVER (PARTITION BY l.junction_id ORDER BY l.log_id)给每个动作的日志条目按ID升序编号(如果需要按记录日期排序,把ORDER BY l.log_id改成ORDER BY l.date即可); - 关联
exercise_workout_junction_table确保只统计指定训练下的动作日志。
- 使用
修正
entriesCTE:- 从
limited_log_entries中筛选出row_num <=3的记录,再统计总数,这样每个动作最多只贡献3条计数。
- 从
计算精度优化:
- 把
*100改成*100.0,避免整数除法导致的精度丢失(比如如果已完成3条、总组数5组,整数除法会得到0,改成100.0后会得到60.0)。
- 把
额外提示
如果你的需求是每个动作的计数不超过其目标组数(而不是固定前3条),可以进一步调整逻辑:比如在limited_log_entries中关联目标组数据表,取MIN(row_num, set_number)作为有效计数,不过这是基于你当前需求的延伸方案,你可以根据实际场景选择。
内容的提问来源于stack exchange,提问作者user13548783
相关产品推荐
相关产品推荐

