SQLite获取本周(周一为一周首日)成本总和返回0问题排查
我正在编写一个Objective-C方法,用来返回Cost表中本周(周一为一周第一天)的所有成本总和,但这个方法始终返回0,实在搞不懂哪里出问题了。
数据库信息
数据库结构

数据内容

我的代码实现
- (float)getthisweekscosts { float sumprice = 0; // We initialize the total price for all the rows NSString *getcurrentcost = [NSString stringWithFormat:@"%@", @"SELECT COSTAMOUNT FROM COST WHERE DATE > DATE('now', 'weekday 0', '-7 days')"]; const char *query_stmt_budget = [getcurrentcost UTF8String]; if (sqlite3_prepare_v2(costDB,query_stmt_budget, -1, &statement, NULL) == SQLITE_OK){ while (sqlite3_step(statement) == SQLITE_ROW){ NSString *currentcost = [NSString stringWithFormat:@"%s",(const char *) sqlite3_column_text(statement, 0)]; sumprice += [currentcost floatValue]; } sqlite3_finalize(statement); } sqlite3_close(costDB); return sumprice; }
问题排查与解决思路
我来帮你捋捋这个问题哈,方法返回0大概率是没查到数据或者数据读取错误,咱们一步步来:
1. SQL查询条件的坑
你当前的SQL语句是SELECT COSTAMOUNT FROM COST WHERE DATE > DATE('now', 'weekday 0', '-7 days'),这里有两个关键问题:
- SQLite里
weekday 0代表的是周日,不是周一!你要把一周第一天设为周一的话,得用weekday 1。 - 这个条件是取「过去7天到现在」的数据,不是严格的「本周(周一到当前)」范围,很可能漏了本周一的部分数据,或者包含了上周日的数据。
给你个精准的SQL写法,确保只取本周一到现在的所有数据:
SELECT COSTAMOUNT FROM COST WHERE DATE >= DATE('now', '-', (strftime('%w', 'now') + 6) % 7 || ' days')
解释下:strftime('%w', 'now')会返回0(周日)到6(周六)的数字,(strftime('%w', 'now') + 6) % 7的作用是把任何日期都转成距离本周一的天数,减去这个天数就能得到本周一的日期,这样不管今天是周几,都能精准匹配本周的数据。
2. 数据读取方式错误
从数据库结构看,COSTAMOUNT是REAL类型(浮点型),但你用sqlite3_column_text把它转成字符串再转float,这中间很容易出问题(比如数值存储格式导致字符串转换失败)。直接用sqlite3_column_double读取才是正确的姿势:
// 替换原来的读取代码 sumprice += sqlite3_column_double(statement, 0);
3. 数据库连接与错误排查
你的代码没做错误日志,万一SQL语句编译失败根本不知道!建议加上错误输出,方便排查:
int prepareResult = sqlite3_prepare_v2(costDB, query_stmt_budget, -1, &statement, NULL); if (prepareResult == SQLITE_OK){ // 循环读取数据 } else { NSLog(@"SQL编译失败:%s", sqlite3_errmsg(costDB)); }
另外,sqlite3_close(costDB)如果放在这里,要是costDB是全局的数据库连接,后续操作会直接报错,建议确认数据库连接的管理逻辑,不要随便关闭。
4. 日期格式校验
最后要确认你的DATE字段是不是YYYY-MM-DD格式!SQLite的DATE()函数只认这个格式,如果你的日期是MM/DD/YYYY或者其他格式,条件判断会完全失效,查不到任何数据。
你可以先在SQLite可视化工具里跑一遍你的查询语句,看看有没有返回结果——如果工具里能查到数据,那就是代码读取的问题;如果工具里也查不到,那就是SQL条件或者日期格式的问题。
修正后的完整代码
- (float)getthisweekscosts { float sumprice = 0; // 精准获取本周一至今的成本数据 NSString *sql = @"SELECT COSTAMOUNT FROM COST WHERE DATE >= DATE('now', '-', (strftime('%w', 'now') + 6) % 7 || ' days')"; const char *query_stmt = [sql UTF8String]; sqlite3_stmt *statement = NULL; int prepareResult = sqlite3_prepare_v2(costDB, query_stmt, -1, &statement, NULL); if (prepareResult == SQLITE_OK){ while (sqlite3_step(statement) == SQLITE_ROW){ // 直接读取REAL类型数值,避免字符串转换错误 sumprice += sqlite3_column_double(statement, 0); } sqlite3_finalize(statement); } else { NSLog(@"SQL编译错误:%s", sqlite3_errmsg(costDB)); } // 注意:如果costDB是全局连接,不要在这里关闭! // sqlite3_close(costDB); return sumprice; }
内容的提问来源于stack exchange,提问作者user8914795

