我有两个相关的表,User和UserDownload,现在我想过滤掉UserDownload,它创建的\u at大于用户创建的\u at加一天,所以python代码是:
result = db.session.query(UserDownload.uid).join(User, UserDownload.uid == User.id).filter(UserDownload.created_at >= User.created_at + timedelta(days=1)).all()
逻辑似乎是正确的,但结果很奇怪,有些结果,用户加一天的创建时间比用户下载的创建时间少,而有些则不然。我检查查询字符串的原始sql是:
SELECT user_downloads.uid AS user_downloads_uid \nFROM user_downloads JOIN users ON user_downloads.uid = users.id \nWHERE user_downloads.created_at >= users.created_at + :created_at_1
真的不知道什么:创造了_在_1的意思。在
例如,结果包含这样一个用户的下载(我替换用户下载.uid使用UserDownload,并按用户的uid查询用户):
user_download.created_at: datetime.datetime(2015, 12, 3, 8, 39, 56)
user.created_at: datetime.datetime(2015, 12, 2, 11, 7, 14)
根据您所使用的后端,您需要您的过滤器来生成类似sql的(对于mysql):
SQLAlchemy不会将
^{pr2}$datetime
对象和InstrumentedAttribute
对象之间的算术转换为DATE_ADD
(或根据后端而定的等效函数)。所以你可以用这个来过滤:它被转换为:
其中,它将
timedelta(days=1)
视为一个文本值,并对其进行参数化。这就是:created_at_1
是一个参数,它在查询中将与查询一起传递给服务器的timedelta
对象保留在查询中的位置(作为补充说明,在MySQL中,timedelta
实际上被转换成一个datetime
对象,这是epoch+1天,因为MySQL没有本机的INTERVAL
类型)。在因此,要让查询执行您想要的,您需要使用
sqlalchemy.func
对象来生成所需的服务器端函数。继续MySQL示例,适当的查询可能是:从而产生:
我发现这个问题很有帮助:Using DATEADD in sqlalchemy
来自评论
好的,我将尝试更详细地了解您最初的查询,但请给我一些自由,因为我正在解决这个问题。让我们暂时忘掉
timedelta
,看看生成的sql是什么。所以这个:生成此sql:
没有什么难找的。现在,当我们在
timedelta
中重新添加时,生成的sql完全相同,只是我们在users.created_at
上添加了一个值,该值由bind参数created_at_1
表示:那么,是先进行比较,还是先进行加法?正在运行此查询。。。在
。。。返回
0
(即False
),这证明加法(2 + 2
)是在比较(>=
)之前解析的。因此,可以安全地假设在您的查询中也发生了这种情况,created_at_1
的值被添加到users.created_at
previor中,与user_downloads.created_at
进行比较。执行查询时,这是传递给服务器的参数值:因此,即使您在过滤器中将}(这是您在上面的参数值字典中看到的值)。在
timedelta(days=1)
添加到users.created_at
中,SQLAlchemy实际上会传递一个datetime
对象,相当于<epoch> + <timedelta>
,或者在本例中:datetime(1970, 1, 1, 0, 0) + timedelta(days=1)
或{那么
user.created_at + datetime(1970, 1, 2, 0, 0)
的值到底是多少?我用User
向数据库中添加了一个User
实例:然后运行以下查询:
它返回:
这是}进行1天的比较。在
user.created_at
的值,不带任何格式,datetime(1970, 1, 2, 0, 0)
的年份部分连接到末尾。这就是您的查询与user_download.created_at
的比较。为了(相对)简洁起见,我不打算研究user_download.created_at
与该值的比较是如何工作的,但希望我已经演示了查询的最终结果不是将user_download.created_at
与{使用该查询,生成的sql如下:
传递给服务器的值是:
因此,您可以看到
datetime + timedelta
部分在传递到数据库之前被解析为,因此,数据库操作是将DATETIME
列与datetime
值的简单比较。在相关问题 更多 >
编程相关推荐