带参数的Pandas read_sql

zujrkrfu  于 2023-03-06  发布在  其他
关注(0)|答案(2)|浏览(102)

有没有在Pandas中用SQL查询传递参数的例子?
特别是我使用SQLAlchemy引擎连接到PostgreSQL数据库。到目前为止,我发现下面的工作:

df = psql.read_sql(('select "Timestamp","Value" from "MyTable" '
                     'where "Timestamp" BETWEEN %s AND %s'),
                   db,params=[datetime(2014,6,24,16,0),datetime(2014,6,24,17,0)],
                   index_col=['Timestamp'])

Pandas文档说params也可以作为一个dict传递,但是我似乎不能让它工作,例如:

df = psql.read_sql(('select "Timestamp","Value" from "MyTable" '
                     'where "Timestamp" BETWEEN :dstart AND :dfinish'),
                   db,params={"dstart":datetime(2014,6,24,16,0),"dfinish":datetime(2014,6,24,17,0)},
                   index_col=['Timestamp'])

从Pandas运行这些类型的查询的推荐方法是什么?

bhmjp9jg

bhmjp9jg1#

read_sql文档说这个params参数可以是一个列表、元组或dict(参见docs)。
要在sql查询中传递值,可能有不同的语法:一米二英寸一英寸、一米三英寸、一米四英寸、一米五英寸、一米六英寸(参见PEP249)。
但并非所有数据库驱动程序都支持所有这些可能性,支持哪种语法取决于您使用的驱动程序(我猜您使用的是psycopg2)。
在第二种情况下,当使用dict时,您使用的是'named arguments',根据psycopg2文档,它们支持%(name)s样式(因此我认为不支持:name),请参见http://initd.org/psycopg/docs/usage.html#query-parameters。
因此,使用这种风格应该会奏效:

df = psql.read_sql(('select "Timestamp","Value" from "MyTable" '
                     'where "Timestamp" BETWEEN %(dstart)s AND %(dfinish)s'),
                   db,params={"dstart":datetime(2014,6,24,16,0),"dfinish":datetime(2014,6,24,17,0)},
                   index_col=['Timestamp'])
7hiiyaii

7hiiyaii2#

我在阅读SQLite表时遇到了传递大量参数的问题。后来发现,既然你传递了一个字符串到read_sql,你就可以只使用f-string。用MSSQL pyodbc尝试了同样的方法,效果也很好。
对于SQLite,它将如下所示:

# write a sample table into memory
from sqlalchemy import create_engine
df = pd.DataFrame({'Timestamp': pd.date_range('2020-01-17', '2020-04-24', 10), 'Value1': range(10)})
engine = create_engine('sqlite://', echo=False)
df.to_sql('MyTable', engine);

# query the table using a query
tpl = (1, 3, 5, 8, 9)
query = f"""SELECT Timestamp, Value1 FROM MyTable WHERE Value1 IN {tpl}"""
df = pd.read_sql(query, engine)

如果参数是datetime,则会稍微复杂一些,但是调用您所使用的SQL方言的datetime转换函数应该可以完成这项工作。

start, end = '2020-01-01', '2020-04-01'
query = f"""SELECT Timestamp, Value1 FROM MyTable WHERE Timestamp BETWEEN STRFTIME("{start}") AND STRFTIME("{end}")"""
df = pd.read_sql(query, engine)

相关问题