Python - 根据日期过滤SQL查询

问题描述 投票:0回答:4

我正在尝试构建一个SQL查询,该查询将根据系统日期进行过滤(查询过去7天内完成的所有销售):

import datetime
import pandas as pd
import psycopg2

con = p.connect(db_details)
cur = con.cursor()

df = pd.read_sql("""select store_name,count(*) from sales 
     where created_at between datetime.datetime.now() - (datetime.today() - timedelta(7))""",con=con)

我收到一个错误

psycopg2.NotSupportedError: cross-database references are not implemented: datetime.datetime.now
python sql python-3.x pandas psycopg2
4个回答
2
投票

您正在将Python语法混合到SQL查询中。 SQL由数据库解析并执行,而不是由Python解析,数据库对datetime.datetime.now()datetime.date()timedelta()一无所知!您看到的特定错误是由于您的Python代码被解释为SQL而不是SQL,datetime.datetime.now引用now数据库中的datetime表的datetime列,这是一个跨数据库引用,而psycopg2不支持查询涉及多个数据库。

而是使用SQL参数将值从Python传递到数据库。在SQL中使用占位符来显示值应该到达的数据库驱动程序:

params = {
    # all rows after this timestamp, 7 days ago relative to 'now'
    'earliest': datetime.datetime.now() - datetime.timedelta(days=7),
    # if you must have a date *only* (no time component), use
    # 'earliest': datetime.date.today() - datetime.timedelta(days=7),
}
df = pd.read_sql("""
     select store_name,count(*) from sales 
     where created_at >= %(latest)s""", params=params, con=con)

这使用psycopg2 parameters documentation定义的占位符,其中%(latest)s引用latest字典中的params键。 datetime.datetime()实例由驱动程序直接支持。

请注意,我还修复了7天前的表达式,并用BETWEEN替换了你的>=语法;如果没有第二个日期,则不会查询两个日期之间的值,因此请使用>=将列限制为给定日期或之后的日期。


1
投票

datetime.datetime.now()不是一个正确的SQL语法,因此不能由read_sql()执行。我建议使用正确的SQL语法来计算当前时间,或者为每个datetime.datetime.now()datetime.today() - timedelta(7)创建变量并在字符串中替换它们。

编辑:不要按照第二个建议。请参阅Martijn Pieters的以下评论。


0
投票

也许您应该删除SQL中的Python代码,在python中计算日期,然后使用strftime函数将它们转换为字符串。

然后,您将能够在SQL查询中使用它们。


0
投票

实际上,您在Python中不一定需要任何参数或计算。只需使用相应的SQL语句,该语句应如下所示:

select store_name,count(*)
from sales 
where created_at >= now()::date - 7
group by store_name

编辑:我还添加了一个我认为缺失的group by

© www.soinside.com 2019 - 2024. All rights reserved.