繁体   English   中英

Pandas to_sql - 附加 DataFrame 时增加表的索引

[英]Pandas to_sql - Increase table's index when appending DataFrame

我一直致力于开发一种产品,该产品以数据分析 Python 3.7.0 脚本的日常执行为中心。 每天午夜,它会处理大量数据,然后将结果导出到两个 MySQL 表中。 第一个将只包含与当天相关的数据,而另一个表将包含所有执行的串联数据。

为了举例说明我目前拥有的内容,请参见下面的代码,假设df将是从数据分析中生成的最终 DataFrame:

import pandas as pd
import sqlalchemy

engine = sqlalchemy.create_engine(r"mysql+pymysql://user:psswd@localhost/pathToMyDB")

df = pd.DataFrame({'Something':['a','b','c']})

df.to_sql('DReg', engine, index = True, if_exists='replace') #daily database
df.to_sql('AReg', engine, index = False, if_exists='append') #anual database

正如您在我的第二个to_sql函数的参数中看到的那样,我没有为 anual 数据库设置索引。 然而,我的经理要求我这样做,创建了一个以一个简单规则为中心的索引:它将是一个自动递增的数字索引,它会自动为数据库中保存的每一行与其位置相对应的行赋予一个数字。

所以基本上,我第一次保存df ,数据库应该如下所示:

index   Something
0       a
1       b
2       c

在我的第二次执行中:

index   Something
0       a
1       b
2       c
3       a
4       b
5       c

但是,当我在第二个df.to_sql命令df.to_sql索引设置为True (将其转换为df.to_sql('AReg', engine, index = True, if_exists='append') )时,两次执行后我的数据库最终会查找喜欢:

index   Something
0       a
1       b
2       c
0       a
1       b
2       c

我做了一些研究,但找不到允许索引自动增加的方法。 我考虑过在每次执行时读取年度数据库,然后调整我的数据帧的索引,但我的数据库很容易变得非常庞大,这会使它的执行速度非常慢(并且还禁止我在两台计算机上同时执行相同的数据分析而无需危及我的索引)。

那么使该索引起作用的最佳解决方案是什么? 我在这里缺少什么?

尽管 Pandas 有很多导出选项,但它的主要目的并不是用作数据库管理 api。 管理索引通常是数据库应该处理的事情。

我建议设置index=False, if_exists='append'并使用自动增量索引创建表:

CREATE TABLE AReg (
     id INT NOT NULL AUTO_INCREMENT,
     # your fields here
     PRIMARY KEY (id)
);

这是我的解决方案。 SQL+Python。

使用 SQL 获取最大索引 id 而不是读取整个表。 它在 DB 和 python 上的负载又快又轻。

更新 id 需要从数据库序列中读取以确保在多用户/会话情况下唯一的 id。

最好设计带有自动增量 id 的表。 如果没有,则需要遵循以下案例。 所有新的 id 都应该从数据库的序列实例中获取。 序列实例可以确保 id 是唯一的,即使是多用户/会话读取。

在 mysql 中,我们手动获取 max id。 在 Oracle 或 postgresql 中,我们可以通过高级 sql 命令获取最大序列 ID。

import pandas as pd
from pprint import pprint
from sqlalchemy import create_engine


db_name = 'temp'
table_name = 'tmp_table'
index_name = 'id'
mysql_url = f'mysql+mysqlconnector://root:Root123@192.168.100.200:13306/{db_name}'
engine=create_engine(mysql_url)

def to_sql_seq(df,table_name=table_name, engine=engine):

    get_seq_id_sql = f"""
                       select your_sequence.nextval as id
                        from dual 
                         connect by level < {df.shape[0]}
                     """

    # sql_get_max_id = f'select max({index_name}) as id from {table_name}'

    s_id = pd.read_sql(get_seq_id_sql , engine)

    df.index =s_id['id'].values
    df.index.name=index_name
    df.to_sql(table_name,engine,if_exists='append')
    return
#Check the current database record
current_table = pd.read_sql(f"select * from {table_name}",engine)
pprint(current_table)

#Simu the new data
new_data = [1,2,3,4]
new_table = pd.DataFrame(new_data,columns=['value'])
to_sql_seq(new_table)

#show the index auto_increment result
inserted_table = pd.read_sql(f'select * from {table_name}',engine)
pprint(inserted_table)

和输出

   id  value
0   1    123
1   2    234
2   3      1
3   4      2
4   5      3
5   6      4
   id  value
0   1    123
1   2    234
2   3      1
3   4      2
4   5      3
5   6      4
6   7      1
7   8      2
8   9      3
9  10      4

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM