[英]Filter sqlalchemy sqlite datetime column by time
我不确定如何仅使用时间字段来完成对数据库的过滤。 现在我有一个名为DatabasePolgygon
的类
class DatabasePolygon(dbBase):
__tablename__ = 'objects'
begin_time = Column(DateTime) # starting time range of shape
end_time = Column(DateTime) # ending time range of shape
# Other entries not relevant to this question
begin_time和end_time可能等于2006-06-01 14:45:23
这样的值,它们表示对象(在本例中是绘图上的形状)所涵盖的X轴范围。 我想允许高级搜索我的用户,特别是要求在一段时间内出现的所有对象。 但是如何使用DateTime
字段完成此操作呢?
# Grab all shapes that appear above this certain time
query_result = query_result.filter(
DatabasePolygon.begin_time >= datetime.strptime(rng['btime']), %H:%M:%S')
)
问题是我正在将日期时间对象与Ymd HMS
与仅具有HMS
的对象进行比较。 一个示例场景是,如果用户想要所有对象,无论年/月/日,是否超出14:45:24的范围,那么我们将有rng['btime']=14:45:24
和begin_time=2006-06-01 14:45:23
在比较时似乎没有实际过滤任何东西。
有没有什么方法可以有效地比较这一列数据中的时间? 我希望能够做类似的事情
# Grab all shapes that appear above this certain time
query_result = query_result.filter(
DatabasePolygon.begin_time.time() >= datetime.strptime(rng['btime']), %H:%M:%S').time()
)
在一些条件下,它似乎是可能的。
目标1:做到这一点(根本)。
使用名为Thing
的类来保存“objects”表中的id
和begin_time
值:
class Thing(Base):
__tablename__ = 'objects'
id = Column(Integer, primary_key=True)
begin_time = Column(DateTime)
def __repr__(self):
return "<Thing(id=%d, begin_time='%s')>" % (self.id, self.begin_time)
并在SQLite数据库的“objects”表中测试数据
id begin_time
-- -------------------
1 1971-01-14 17:21:53
2 1985-05-24 10:11:12
3 1967-07-01 13:14:15
不幸的是,这不起作用:
engine = create_engine(r'sqlite:///C:\__tmp\test.db', echo=True)
Session = sessionmaker(bind=engine)
session = Session()
for instance in session.query(Thing)\
.filter(Thing.begin_time[11:]<'17:00:00')\
.order_by(Thing.id):
print(instance)
生产
NotImplementedError:此表达式不支持运算符'getitem'
但是,这确实有效......
engine = create_engine(r'sqlite:///C:\__tmp\test.db', echo=True)
conn = engine.connect()
result = conn.execute("SELECT id FROM objects WHERE substr(begin_time,12)<'17:00:00'")
id_list = [row[0] for row in result.fetchall()]
result.close()
conn.close()
Session = sessionmaker(bind=engine)
session = Session()
for instance in session.query(Thing)\
.filter(Thing.id.in_(id_list))\
.order_by(Thing.id):
print(instance)
目标2: 有效地做到这一点。
控制台输出向我们显示第一个SELECT确实是
SELECT id FROM objects WHERE substr(begin_time,12)<'17:00:00'
所以如果我们使用SQLite 3.9.0或更高版本并创建了“表达式索引”
CREATE INDEX time_idx ON objects(substr(begin_time,12));
那么SQLite就能避免表扫描。 不幸的是,即便是最新发布的CPython 2.7(2.7.11)仍然附带一个sqlite3
模块太旧了
Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec 5 2015, 20:32:19) [MSC v.1500 32 bit (Intel)] on win32
>>> import sqlite3
>>> sqlite3.sqlite_version
'3.6.21'
所以索引不能存在于数据库中,否则SQLAlchemy会阻塞它:
sqlalchemy.exc.DatabaseError:(sqlite3.DatabaseError)格式错误的数据库架构(time_idx) - 接近“(”:语法错误[SQL:“SELECT id FROM objects WHERE substr(begin_time,12)<'17:00:00'”]
因此,如果“高效”部分非常重要,那么您可能需要说服Python使用更新版本的SQLite。 关于这方面的一些指导可以在问题中找到
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.