首页 > 解决方案 > 在过滤器中使用日期时 SQLAlchemy 中的不匹配

问题描述

我有一个Opinion在 PostgreSQL 数据库中调用的表,其中包含几列。但是,相关的是:

让这个查询:

select count(*) 
from opinion o 
where report_version_id = 14 
and assigned = true 
and date_trunc('day', content_created_at) = '2021-05-23';

使用 DBeaver 客户端,我得到一个计数:374,但是在 Python 脚本(v3.7)中使用 SQLAlchemy(v1.4.11)时,我得到另一个计数,372。这是 Python 中使用的代码:

return (session.query(Opinion).filter(func.date_trunc('day', Opinion.content_created_at) == date)
        .filter(Opinion.report_version_id == report_version_id,
                Opinion.assigned == True)
        .count())

我玩过并在不使用所有匹配的日期的情况下进行计数,所以我的猜测是 1)我做错了并且不知道,或者 2)在处理过滤器中的日期时,此版本中存在错误。

我完全确定我已连接到同一个数据库,并且在从 2 个不同的源(我运行 Python 脚本的本地 DBeaver 客户端和终端)连接时没有执行任何事务。

编辑:

这是我在编译时得到的查询:

SELECT opinion.report_version_id ...
FROM opinion 
WHERE date_trunc(%(date_trunc_1)s, opinion.content_created_at) = %(date_trunc_2)s 
AND opinion.report_version_id = %(report_version_id_1)s 
AND opinion.assigned = true

根据 Anudeep 在他的回答中建议,我添加了文字查询:

SELECT opinion.report_version_id ...
FROM opinion 
WHERE date_trunc('day', opinion.content_created_at) = '2021-05-23' 
AND opinion.report_version_id = 14 
AND opinion.assigned = true

我还比较了使用 DBeaver 客户端和脚本得到的结果,我似乎得到了更多,因为应用的时区有所不同。我得到的记录是从第二天(2021-05-24)提前 1 小时内开始的。

回答

检查连接时的时区是否与将此数据插入数据库时​​的时区相同。您可以像这样设置此配置:

creds = {
    "url": f"{DB_ENGINE}://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}",
    "echo": False,
    "connect_args": {
        "options": "-c timezone=utc-1"
    }
}
session = sessionmaker(bind=engine or sqlalchemy.engine_from_config(creds, prefix=""))()

标签: pythonsqlalchemy

解决方案


也许您可以尝试使用文字绑定参数打印查询,并检查您是否在 python 查询中设置了正确的值。

print(q.statement.compile(compile_kwargs={"literal_binds": True}))

推荐阅读