pandas' read_sql 包含 WHERE 条件的值列表

pandas' read_sql with a list of values for WHERE condition

假设一个数据帧scoreDF:

          date       time      score
sec_code
1048      2015-02-25 09:21:00     28
2888      2015-02-25 09:21:00     25
945       2015-02-25 09:21:00     23
4         2015-02-25 09:21:00     22
669       2015-02-25 09:21:00     15

我需要进行 MySQL 查询以检索与 scoreDF.index 中的值匹配的所有行,即 sec_code 列。

通常我会去循环:

    finalResultDF = DataFrame()

    queryString = 'SELECT * FROM tableA WHERE sec_code = ' + code

    for code in scoreDF.index:
        queryResultDF = sql.read_sql(queryString, con)
        finalResultDF.append(queryResultDF)

是否可以在没有循环传递值列表的情况下以不同的方式执行此操作,即 scoreDF.index 作为 WHERE 条件?我用 Google 搜索了几个小时,有些人提到了 'parameter' 到 read_sql,但我无法弄清楚。

您实际上可以在没有任何循环的情况下执行此操作。

queryString = 'SELECT * FROM tableA WHERE sec_code in '+tuple(scoreDF.index)

这将给出结果 directly.This 假设 scoreDF.index 是一个 list。如果它已经是一个 tuple 则不需要类型转换。

正如 bolec_kolec 所建议的,我认为最佳做法是在调用 read_sql 时使用 params。这是我通常的做法 (Python 3.7):

scoreIndex = scoreDF.index.tolist() 
queryString = 'SELECT * FROM tableA WHERE sec_code = ANY(%(scoreIndex)s)'

queryParams = {'scoreIndex': scoreIndex}
queryResultDF = sql.read_sql(sql = queryString, con, params = queryParams)

以下适用于 SQL 服务器(标记为 ?)并避免 SQL 注入。我们根据需要用 ? 填充查询字符串。然后,我们通过 params.

传递值列表
queryString = """
  SELECT * FROM tableA
  WHERE sec_code in ({})
""".format(','.join(['?'] * len(scoreDF.index)))

queryResultDF = sql.read_sql(sql = queryString, con, params = scoreDF.index)