我正在尝试构建一个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查询中。 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
替换了你的>=
语法;如果没有第二个日期,则不会查询两个日期之间的值,因此请使用>=
将列限制为给定日期或之后的日期。
datetime.datetime.now()
不是一个正确的SQL语法,因此不能由read_sql()
执行。我建议使用正确的SQL语法来计算当前时间,或者为每个datetime.datetime.now()
和datetime.today() - timedelta(7)
创建变量并在字符串中替换它们。
编辑:不要按照第二个建议。请参阅Martijn Pieters的以下评论。
也许您应该删除SQL中的Python代码,在python中计算日期,然后使用strftime函数将它们转换为字符串。
然后,您将能够在SQL查询中使用它们。
实际上,您在Python中不一定需要任何参数或计算。只需使用相应的SQL语句,该语句应如下所示:
select store_name,count(*)
from sales
where created_at >= now()::date - 7
group by store_name
编辑:我还添加了一个我认为缺失的group by
。