在pandas或psycopg2中发布Postgres 9.5 upsert命令?

时间:2017-03-09 12:26:45

标签: pandas psycopg2 postgresql-9.5

我看到的大多数示例都是人们使用ON CONFLICT DO UPDATE语法将一行插入数据库。

有没有人使用SQLAlchemy或pandas.to_sql?

99%的插件都使用psycopg2 COPY命令(所以我保存了csv或stringio然后批量插入),另外1%是pd.to_sql。我检查新行或维度的所有逻辑都是用Python完成的。

def find_new_rows(existing, current, id_col):
        current[id_col] = current[id_col].astype(int)
        x = existing[['datetime', id_col, 'key1']]
        y = current[['datetime', id_col, 'key2']]
        final = pd.merge(y, x, how='left', on=['datetime', id_col])
        final = final[~(final['key2'] == final['key1'])]
        final = final.drop(['key1'], axis=1)
        current = pd.merge(current, final, how='left', on=['datetime', id_col])
        current = current.loc[current['key2_y'] == 1]
        current.drop(['key2_x', 'key2_y'], axis=1, inplace=True)
        return current

有人能告诉我一个使用新的PostgreSQL语法与pyscopg2进行upsert的示例吗?一个常见的用例是检查尺寸变化(每天50k到100k行,我将其与现有值进行比较),这是CONFLICT DO NOTHING只添加新行。

另一个用例是我有随时间变化的事实数据。我只采用最近的值(我目前使用视图来选择不同的),但如果可能的话,UPSERT会更好。

2 个答案:

答案 0 :(得分:0)

仅供参考,这是我目前正在使用的解决方案。

它似乎对我的目的很好。我必须添加一行来替换null(NaT)时间戳,但是因为当我将每一行加载到数据库时出现错误。

setInterval

答案 1 :(得分:0)

这是我的代码,用于从熊猫数据框中批量插入和在冲突更新查询中为postgresql插入:

假设ID是postgresql表和pandas df的唯一键,并且您要基于此ID进行插入和更新。

import pandas as pd
from sqlalchemy import create_engine, text

engine = create_engine(postgresql://username:pass@host:port/dbname)
query = text(f""" 
                INSERT INTO schema.table(name, title, id)
                VALUES {','.join([str(i) for i in list(df.to_records(index=False))])}
                ON CONFLICT (id)
                DO  UPDATE SET name= excluded.name,
                               title= excluded.title
         """)
engine.execute(query)

确保df列与表的顺序必须相同。