Python 使用SQLAlchemy过滤彼此相隔两秒钟的对象
我有两个表,列为“date”。一个保持(名称、日期),另一个保持(日期、p1、p2)。给定一个名称,我想使用表1中的日期从表2中查询p1和p2;如果表1中的日期在表2中日期的两秒内,则应进行匹配 如何使用SQLAlchemy实现这一点 我已尝试(未成功)使用Python 使用SQLAlchemy过滤彼此相隔两秒钟的对象,python,database,datetime,sqlalchemy,Python,Database,Datetime,Sqlalchemy,我有两个表,列为“date”。一个保持(名称、日期),另一个保持(日期、p1、p2)。给定一个名称,我想使用表1中的日期从表2中查询p1和p2;如果表1中的日期在表2中日期的两秒内,则应进行匹配 如何使用SQLAlchemy实现这一点 我已尝试(未成功)使用between运算符和一个类似以下的子句: td = datetime.timedelta(seconds=2) q = session.query(table1, table2).filter(table1.name=='my_name')
between
运算符和一个类似以下的子句:
td = datetime.timedelta(seconds=2)
q = session.query(table1, table2).filter(table1.name=='my_name').\
filter(between(table1.date, table2.date - td, table2.date + td))
有什么想法吗
编辑:
我通过以下方法解决了这个问题:
from sqlalchemy.sql import between
import datetime
# [all other relevant imports]
td = datetime.timedelta(seconds=2)
t1_entry = session.query(table_1).filter(table_1.name == 'the_name').first()
if t1_entry is not None:
tmin = t1_entry.date - td
tmax = t1_entry.date + td
t2_entry = session.query(table_2).filter(between(table_2.date, tmin, tmax)).first()
return (t1_entry, t2_entry)
return None
因此可以进行比较,但我不确定该方法是否有效。首先让我解释一下为什么您尝试的方法无效。SQLAlchemy只是编写SQL查询的一种方便方法,尽管如此,所有查询都发生在远程端。SQLAlchemy列是一些特殊对象,它们的
\uuuuueq\uuuuuuuuu
,\uuugt\uuuuuuuuu
等方法会被覆盖,以返回的不是True
或False
,而是其他特殊对象,它们会记住与它们进行比较的对象是什么,并且可以在以后生成适当的SQL语句。添加etc也是如此:自定义的\uuuuu add\uuuuu
,\uuuu sub\uuuu
方法不返回数字或串联字符串,但也返回生成sql语句的对象。您可以将它们与字符串、整数等、其他列、select语句、mysql函数调用等进行比较/添加,但不能与特殊的python对象(如TimeDelta)进行比较/添加。(简化,技术上可能不是100%正确;)
因此,您可以做的是:
- 将数据库中的值设为整数,例如unix时间戳。这样,您的
查询将起作用(使用between
而不是delta)2
- 使用数据库端函数将日期时间格式日期转换为unix时间戳,然后进行比较
>>> db.session.execute(db.select([User.date_joined, User.date_joined + timedelta(seconds=2)], limit=1)).fetchall()
[(datetime.datetime(2009, 7, 10, 20, 47, 33), 20090710204733.0)]
>>> db.session.execute(db.select([User.date_joined, User.date_joined + 2], limit=1)).fetchall()
[(datetime.datetime(2009, 7, 10, 20, 47, 33), 20090710204735.0)]
>>> db.session.execute(db.select([User.date_joined+0, User.date_joined + 2], limit=1)).fetchall()
[(20090710204733.0, 20090710204735.0)]
SQLite:
>>> db.session.execute(db.select([User.date_joined, User.date_joined + timedelta(seconds=2)], limit=1)).fetchall()
TypeError: expected string or buffer
>>> db.session.execute(db.select([User.date_joined, User.date_joined + 2], limit=1)).fetchall()
[(datetime.datetime(2010, 5, 28, 23, 8, 22, 476708), 2012)]
>>> db.session.execute(db.select([User.date_joined+0, User.date_joined + 2], limit=1)).fetchall()
[(2010, 2012)]
我不知道为什么第一个在MySQL上失败,为什么它返回float。SQLite错误似乎是因为SQLite而发生的
你必须稍微考虑一下,也许你会找到一种有效的方法——但我认为要保持真正的dbms独立性,整数方法将是唯一可行的方法。经过一段时间的讨论,这个问题仍然悬而未决,到目前为止,我提出的方法是:
from sqlalchemy.sql import between
import datetime
# [all other relevant imports]
td = datetime.timedelta(seconds=2)
t1_entry = session.query(table_1).filter(table_1.name == 'the_name').first()
if t1_entry is not None:
tmin = t1_entry.date - td
tmax = t1_entry.date + td
t2_entry = session.query(table_2).filter(between(table_2.date, tmin, tmax)).first()
return (t1_entry, t2_entry)
return None
如果您有更好的想法,我将接受您的答案。方法是将日期转换为unix时间戳 在最近的一段代码中,我成功地使用了以下几行:
from sqlalchemy.sql import func
...
q = q.join(q2, func.abs(func.unix_timestamp(rssi1.datetime)-func.unix_timestamp(q2.c.datetime)) <=2 )
来自sqlalchemy.sql导入函数
...
q=q.join(q2,func.abs(func.unix_timestamp(rssi1.datetime)-func.unix_timestamp(q2.c.datetime))时间对象的不同格式可能会成为一个令人头痛的问题!