Python 如何筛选日期时间字段+;/-使用SQLalchemy的日期时间

Python 如何筛选日期时间字段+;/-使用SQLalchemy的日期时间,python,mysql,datetime,sqlalchemy,Python,Mysql,Datetime,Sqlalchemy,我有一个mysql表,表示编辑文章及其元数据,如标题、作者和datecreated 我有另一个表,表示在不同时间点计算的关于这些文章的度量(例如视图计数)。每一行都是特定文章在特定时刻的这些度量的记录 我想检索metrics表中的所有行,其中metric row timestamp字段在相关文章的datecreated字段过去一小时后的两小时内。我想使用SQLalchemy来完成此操作。 我当前的SQLalchemy查询如下所示: import sqlalchemy as sa import m

我有一个mysql表,表示编辑文章及其元数据,如标题、作者和datecreated

我有另一个表,表示在不同时间点计算的关于这些文章的度量(例如视图计数)。每一行都是特定文章在特定时刻的这些度量的记录

我想检索metrics表中的所有行,其中metric row timestamp字段在相关文章的datecreated字段过去一小时后的两小时内。我想使用SQLalchemy来完成此操作。

我当前的SQLalchemy查询如下所示:

import sqlalchemy as sa
import models as m

s = session()
q = (s.query(m.Article.fb_shares, func.avg(m.ArticlesMetric.views)),
 .join(m.ArticlesMetric)
 .filter(sa.between(m.ArticlesMetric.tstamp,
         m.Article.created + timedelta(hours=1),
         m.Article.created + timedelta(hours=3))
        )
 .group_by(m.Article.id))

result = q.all()
s.close()
但是,这会导致以下错误:

Warning: (1292, u"Truncated incorrect DOUBLE value: '1970-01-01 05:30:00'")

当尝试在不同类型之间进行比较时,mySQL在内部将不同类型的数据强制转换为两倍,然后再进行比较。我相信这个错误在某种程度上是由于使用了timedelta,但是我不确定我如何才能实现我想要做的事情。欢迎任何建议。

事实上,这比看起来要难。如果您直接在MySQL中执行此操作,您将编写以下内容:

SELECT ...
FROM ...
JOIN ...
WHERE tstamp BETWEEN DATE_ADD(created, INTERVAL 1 HOUR) AND DATE_ADD(created, INTERVAL 3 HOUR)
GROUP BY ...
您必须对SQLAlchemy做或多或少相同的事情,因为
m.Article.created
不是一个常数

如果启用查询日志记录,您可以看到代码生成的MySQL查询,并发现它与您的想法不一致:

INFO:sqlalchemy.engine.base.Engine:SELECT test.id AS test_id, test.dt AS test_dt, test.tp AS test_tp 
FROM test 
WHERE test.tp BETWEEN test.dt + %(dt_1)s AND test.dt + %(dt_2)s
INFO:sqlalchemy.engine.base.Engine:{'dt_1': datetime.datetime(1970, 1, 1, 1, 0), 'dt_2': datetime.datetime(1970, 1, 1, 3, 0)}

我设法找到了一种方法来做你想做的事,下面是代码:

from sqlalchemy.sql import func
from sqlalchemy.sql.expression import text

...
filter(sa.between(m.ArticlesMetric.tstamp,
     func.date_add(m.Article.created, text('INTERVAL 1 HOUR')),
     func.date_add(m.Article.created, text('INTERVAL 3 HOUR')))

您是如何定义
m.Article.created
m.ArticlesMetric.tstamp
列的?
created=Column(DateTime)
以及
m.ArticlesMetric.tstamp
呢?
tstamp=Column(DateTime,nullable=False)
fwiw,这个解决方案确实对我有效。看起来您的某个字段正以某种方式转换为非datetime类型。这没有意义,因为您已经验证了数据类型。如果这仍然是个问题,我会用硬编码的日期时间替换您传递到
between()
的所有三个日期时间。如果查询“有效”,那么试着一次添加一个片段——一个timedelta,然后是一个实列,还有另一个timedelta,等等——然后看看哪个部分会破坏它。可能您对测试和产品使用了不同的模型定义,并且其中只有一个正确定义了日期时间?