【问题标题】:Pass object to python SQL将对象传递给 python SQL
【发布时间】:2014-04-25 21:05:53
【问题描述】:

我有一个从 ODBC 连接中提取的 pandas df:

import pandas.io.sql as psql
handle = pyodbc.connect('...')
df1 = psql.frame_query("select * from Table1 where... [some queries on columns]")
# below is a pandas df resulting from the above SQL query
df1 = pd.DataFrame([[1, 'F', 11111, 500, 60], [2, 'M', 22222, 400, 30], [3, 'M', 33333, 5400, 78], [4, 'F', 44444, 5400, 45], [5, 'M', 55555, 8914, 66]], columns = ['ID','Gender','ZipCd','Spend','Age'])

现在我想在同一个数据库中的不同表上运行一个单独的查询;并作为条件之一,从df1 中提取与 ID 匹配的行(例如,下面的行不工作)。

df2 = psql.frame_query("select * from Table2 where ID = ? and StatusCd in ('104', '106', '112', '115')", df1['ID'])
# The ID variable is a common unique identifier b/n the 2 tables

我的问题是,如何将df1['ID'] 分配为要在df2 中查询的元素列表?例如...where ID in (1,2,3,...),但使用 df1['ID'] 作为包含列表的对象。这将返回 df2 中的 ID 与 df1 以及其他查询条件匹配的记录。

我熟悉 w/R 语法,所以从概念上讲,我的问题非常类似于这个问题:Pass R variable to RODBC's sqlQuery?

归根结底,我有兴趣解析表 1,以便它仅包含在表 2 中找到的记录(即具有在表 2 中找到的必需 StatusCd 之一)。在这方面,我确信有一种更有效的方式来调用数据,并且可能在一个查询中,但我对 python 或 SQL 的了解还不够。

进一步评论

我有 pyodbc 作为标签,因为我最初是使用该模块从我的 SQL 服务器中提取的;也许 pyodbc 是用于此类任务的更有效方法?但我是一个 R/电子表格专家,到目前为止,pandas 对我来说是最容易学习的东西。

【问题讨论】:

  • df1[ID] 是一列。您想要对每个元素进行单独查询,对所有元素进行一次查询,还是对其中 1 个元素进行一次查询?
  • @PaulH 如果您指的是应该如何对待df1['ID'],我相信我正在寻找一个查询 df1$ID 中的所有/任何元素。我已根据您的问题相应地编辑了我的帖子。

标签: python mysql pandas pyodbc


【解决方案1】:

frame_query 接受可选的 params 关键字参数,该参数可以是要在 SQL 查询中使用的参数列表或元组。为了能够包含参数列表,您可以使用 python 的字符串格式来包含正确数量的占位符。

例如:

placeholders = ','.join(['?'] * df1['ID'].count())
query = ("select * from Table2 where ID in ({}) "
         "and StatusCd in ('104', '106', '112', '115')").format(placeholders)
df2 = psql.frame_query(query, params=df1['ID'].tolist())

如果有三个 ID,查询字符串将为 select * from Table2 where ID in (?, ?, ?) and StatusCd in ('104', '106', '112', '115')

您可以发送的参数数量是有限制的,因此如果您的参数数量非常多,您可能希望批量执行多个查询,然后连接生成的 DataFrame。

【讨论】:

  • 我不知道...我有大约 100K+ 个 ID 可供搜索。看起来会很多?s
  • 恐怕这是在查询中包含df1['ID'] 的唯一方法,因为 pyodbc 不知道如何处理系列。您还必须使用ID in (...),因为 Series 等效于数组。正如我所提到的,如果 ID 太多,或者 ID 代表表中总行的很大一部分,则可以将其拆分为多个不同的查询,然后查询整个表并连接生成的 DataFrame。哪个是最佳解决方案(具有多个参数的单个查询与多个查询与整个表)取决于您的数据,因此您需要进行试验。
【解决方案2】:

在您的原始查询中使用INNER JOIN 以从table1 返回与table2 中的ID 匹配的行,以获得您需要的状态代码。当您使用它时,将状态代码放入一个变量中并参数化 SQL 语句的执行。代码看起来像这样:

...
codes = ("104", "106", "112", "115")
sql = """select Table1.*
         from Table1
         inner join Table2
            on Table1.ID = Table2.ID
         where Table2.StatusCd in (?, ?, ?, ?)"""
df1 = psql.frame_query(sql, codes)
...

【讨论】:

    【解决方案3】:

    我认为这个问题的答案在于构建一个更好的 SQL 查询:

    psql.frame_query("select... from Table1 as t1
                     inner join Table 2 t2
                     on t1.ID = t2.ID
                     where [add various queries from both tables]", handle)
    

    关闭这篇文章,因为它更适合一个 SQL 问题并用基本文档回答。

    【讨论】:

      猜你喜欢
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-06
      • 1970-01-01
      • 2018-03-05
      • 2012-04-04
      • 2013-10-12
      相关资源
      最近更新 更多