做网站挣钱,wordpress的PC端和移动端,江苏网站建设效果好,兼职做网站安全么记录一个开发过程遇到的小bug#xff0c;构造些伪数据还原并解释。
场景#xff1a;传参触发了查询条件#xff0c;数据库中是存在传参对应范围的数据#xff0c;但是通过查询条件得到的查询结果为空入参场景一#xff1a;
start_… 记录一个开发过程遇到的小bug构造些伪数据还原并解释。 场景传参触发了查询条件数据库中是存在传参对应范围的数据但是通过查询条件得到的查询结果为空入参场景一
start_time 2023-11-13
end_time 2023-11-13
入参场景二
start_time 2023-11-10
end_time 2023-11-15表字段time 类型定义
timedatetime
表字段time下的值为
2023-11-13 00:00:00
2023-11-13 11:00:00
...
查询条件
query session.query(model).filter(model.time start_time, alarm_model.time end_time, model.name.in_(name_list))
使用入参场景一的参数值查询得到的结果就是空
使用入参场景二的参数值就可以查询到2023-11-13对应的值原因分析说明
time 字段类型和入参参数类型不同其中 filter(model.time start_time, alarm_model.time end_time) 这里的条件转换成SQL就是 WHERE time ‘2023-11-13’ AND time ‘2023-11-13’。 这样就是在和 time这个时间字段做直接字符串比较所以 ‘2023-11-13’ 不能匹配 2023-11-13 16:02:36’格式的时间。
解决方案找两种分析
方案一使用完整的时间字符串而不是只用日期这样会形成一个时间范围就能和time的时间格式匹配
WHERE time 2023-11-13 00:00:00 AND time 2023-11-13 23:59:59但是这个方案有一个弊端需要数据库扫描整个时间范围内的time值如果这一天的数据量很大查询会比较慢。
方案二使用日期函数提取日期部分只需要对比日期部分跳过时间部分的比较利用索引查询效率会更高。
import sqlalchemy as sa
或者
from sqlalchemy import funcquery session.query(model).filter(sa.func.date(model.time) start_date,model.time end_time, model.name.in_(name_list))
)
或者
query session.query(model).filter(func.date(model.time) start_date,model.time end_time, model.name.in_(name_list))
)
区别主要在于:方式1 通过sqlalchemy模块名作为前缀,定义别名,访问func子模块避免与当前命名空间冲突
方式2 直接导入func到当前命名空间直接使用从性能的角度来说 1完整时间范围查询会全表扫描指定日期内所有记录, IO和计算量都很大。 2使用日期函数过滤可以省去时间部分的比对,可以利用索引,查询效率会更高。 具体问题看表和索引情况但正常情况使用日期函数提取日期部分查询要更优于完整的时间范围查询。
如以下的索引方式 MySQL索引 名字idx_alarm 字段time, name, extend 索引类型NORMAL 索引方法BTREE 案例这个idx_alarm是一个普通的多列索引,包含time, name, extend三个字段,使用的是BTREE索引。
WHERE DATE(time) 2023-11-13这个条件就会命中索引。DATE(time) 对字段做了转换但是不会打破索引关系。WHERE条件使用了time列的计算值进行等值匹配根据索引最左前缀原则索引包含查询条件中的列所以会被用到。