【问题标题】:DataFrame comparison with SQL Server table and upload just the differencesDataFrame 与 SQL Server 表比较并仅上传差异
【发布时间】:2021-07-23 12:32:14
【问题描述】:

我有一个包含数据的 SQL 表 (table_1),我有一个读取 csf 并创建数据帧的 Python 脚本。

我想将数据帧与 SQL 表数据进行比较,然后将数据帧中缺失的数据插入到 SQL 表中。

我四处阅读了这篇comparing pandas dataframe with sqlite table via sqlqueryCompare pandas dataframe columns to sql table dataframe columns 的帖子,但没能做到。

表格和数据框具有完全相同的列。

数据框是:

import pandas as pd

df = pd.DataFrame({'userid':[1,2,3],
           'user': ['Bob', 'Jane', 'Alice'], 
                   'income': [40000, 50000, 42000]})

和 SQL 表(使用 SQLAlchemy):

userid user income
1      Bob  40000
2      Jane 42000

我想将 df 与 SQL 表进行比较,并插入用户 ID 3 Alice,以及她的所有详细信息,这是它们之间唯一缺少的值。

【问题讨论】:

  • 添加一些重现您的实际问题的示例数据。查看更多详情here
  • 谢谢!所以数据框是 import pandas as pd df = pd.DataFrame({'userid':[1,2,3], 'user': ['Bob', 'Jane', 'Alice'], 'income': [ 40000, 50000, 42000]})和 sql 表(使用 sqlalchemy)用户 ID 用户收入 1 Bob 40000 2 Jane 42000 我想做的是将 df 与 sql 表进行比较并插入用户 ID 3 Alice 及其所有详细信息s 他们之间唯一缺少的值
  • 如果SQL表中存在记录,是更新SQL记录,还是只插入新记录?
  • @JasonCook ,感谢您的回复!对于这种特殊情况,只需插入新的。
  • 你能分享更多关于你是如何连接的吗? pyodbc 可能吗?我在想一个好的方法可能是将值插入到 SQL 临时表中,然后发出另一个 SQL 语句来进行比较和插入。

标签: python sql sql-server pandas dataframe


【解决方案1】:

由于您只对插入新记录感兴趣,并且正在从 CSV 加载,因此您已经在本地内存中拥有数据:

# read current userids
sql = pd.read_sql('SELECT userid FROM table_name', conn)

# keep only userids not in the sql table
df = df[~df['userid'].isin(sql['userid'])]

# insert new records
df.to_sql('table_name', conn, if_exists='append')

其他选项需要首先将比需要更多的数据加载到 SQL 中。

【讨论】:

    【解决方案2】:

    仍然缺少一些信息来提供完整的答案。例如,您使用什么数据库引擎(SQLalchemy、sqlite3)?我假设 id 是唯一的,应该添加所有新的 id 吗?

    如果您使用的是 SQLalchemy,您可以查看pangres,它可以从 pandas 数据帧插入和更新 SQL 数据库。但是,它确实需要数据库中具有 UNIQUE 属性的列(这意味着其中的每个条目都是唯一的,您可以在此处设置 id 列 UNIQUE)。这种方法比从数据库中加载所有数据并在 python 中进行比较具有更好的扩展性,因为只有 csf 数据在内存中,并且数据库进行比较。

    如果你想在 Python 中完成这一切,一个选项是将 SQL 表加载到 pandas 中并根据 user_id 列合并数据:

    import pandas as pd
    df = pd.DataFrame({'userid': [0, 1, 2],'user': ['Bob', 'Jane', 'Alice'], 'income': [40000, 50000, 42000]})
    
    sqldf = pd.read_sql_query("SELECT * FROM table_1",connection)
    df = df.merge(sqldf,how='left' left_on='userid', right_on='userid')
    
    

    然后你可以用新表替换旧表。 编辑: 我看到另一个使用合并的答案,但保留新值并仅将它们发送到数据库。这比上面的代码更干净。

    【讨论】:

    • 感谢您的回复,我将在未来研究 pangres!
    【解决方案3】:

    为什么不直接加入表格?

    conn = #your connection
    df = pd.DataFrame({'userid':[1,2,3],
         'user': ['Bob', 'Jane', 'Alice'], 
         'income': [40000, 50000, 42000]})
    sql = pd.read_sql("SELECT * FROM table", con = conn)
    
    joined = pd.merge(df, sql, how = "left", on = "userid")
    joined = joined[pd.isna(joined["user_y"])]
    index = joined["userid"].tolist()
    

    变量index 现在包含所有仅在df 中但不在sql 中的用户ID。

    插入数据库

    columns = ("userid", "user", "income")
    for i in index:
        data = tuple(df[df["userid"] == i].values.tolist()[0])
        data = [str(x) for x in data]
        sql = f"""INSERT INTO table {columns}
              VALUES {data}"""
        conn.execute(sql)
    

    【讨论】:

      猜你喜欢
      • 2011-05-24
      • 2013-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-22
      • 2020-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多