gpt4 book ai didi

python - 按时间过滤sqlalchemy sqlite datetime列

转载 作者:行者123 更新时间:2023-11-28 16:27:57 26 4
gpt4 key购买 nike

我不确定如何仅使用时间字段来完成对数据库的过滤。现在我有一个名为 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 等值,它们表示对象(在本例中为形状超过情节)涵盖。我想允许对我的用户进行高级搜索,特别是询问在某个时间范围内出现的所有对象。但是,如何使用 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')
)

问题是我将带有 Y-m-d H-M-S 的日期时间对象与仅带有 H-M-S 的对象进行比较。一个示例场景是,如果用户想要所有出现在 14:45:24 范围之外的对象,而不考虑年/月/日,那么我们将有 rng['btime']=14:45: 24begin_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”表中的 idbegin_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: Operator 'getitem' is not supported on this expression

但是,这确实有效......

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) malformed database schema (time_idx) - near "(": syntax error [SQL: "SELECT id FROM objects WHERE substr(begin_time,12)<'17:00:00'"]

因此,如果“高效”部分真的很重要,那么您可能需要说服 Python 使用更新版本的 SQLite。可以在问题中找到一些指导

Force Python to forego native sqlite3 and use the (installed) latest sqlite3 version

关于python - 按时间过滤sqlalchemy sqlite datetime列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34845124/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com