当前位置: 首页 > 科技观察

Python+SQL的无敌组合值得你Pick

时间:2023-03-12 17:08:27 科技观察

SQL是StructuredQueryLanguage的缩写,是一种数据库查询和编程语言,用于访问数据,查询、更新和管理关系数据库系统。在正式讲解代码之前,先普及一下数据库相关的知识。数据库是以一定方式存储在一起的数据集合,可以被多个用户共享,尽可能少的冗余,并且独立于应用程序。数据库系统具有以下特点:①数据结构化实现了整体数据的结构化。这里所说的“整体”结构化,是指数据库中的数据不再只是针对某个应用,而是针对整个组织;不仅数据内部是结构化的,而且是整体结构化的,数据之间是有联系的。②数据共享度高。多个用户可以同时访问数据库中的数据,甚至可以同时访问数据库中的相同数据。③数据冗余度低,减少了重复数据的存储,节省了存储空间。④数据独立性高用户的应用程序与数据库的物理存储结构和逻辑结构相互独立。数据库可以分为两类,关系数据库和非关系数据库NoSQL(NotOnlySQL)。关系型数据库是由多个可以相互连接的二维行-列表组成的数据库。非关系型数据库NoSQL主要是指非关系型、分布式、无ACID的数据库设计模式。其中,ACID指的是数据库事务处理的四大基本要素,分别代表原子性、一致性、隔离性和持久性。这里重点介绍关系型数据库,如常用的Oracle、MySQL、MicrosoftSQLServer、PostgreSQL等。下面将以PostgreSQL为例,讲解如何用Python连接数据库,并用SQL进行后续操作。【工具】Python3PostgreSQL10Tushare【注意】本文假设您已经安装了PostgreSQL数据库,您可以直接从官网下载安装。文章代码部分侧重于方法讲解,希望大家根据自己的需要灵活运用。01.使用Python连接数据库PostgreSQLPostgreSQL是最先进、应用最广泛的关系型数据库管理系统之一。它非常受欢迎的原因有很多,包括它是开源的、它的可扩展性以及它处理许多不同类型的应用程序和不同负载的能力。可以使用Python轻松建立与PostgreSQL数据库的连接。PostgreSQL的Python驱动程序有很多,其中“psycopg”是最流行的,它的当前版本是psycopg2。我们可以使用psycopg2模块将Postgres与Python连接起来。psycopg2是Python的Postgres数据库适配器。首先,您需要使用pip命令安装它。$pip3installpsycopg2【注意】这里使用的版本是Python3.5,所以使用pip3代替pip进行安装。安装完成后,我们就可以使用它来进行数据库连接操作了。首先,应该创建一个代表数据库的连接对象con。接下来,创建一个游标对象cur来执行SQL语句。importpsycopg2con=psycopg2.connect(database="postgres",user="postgres",password="Kaliakakya",host="127.0.0.1",port="5432")print("数据库打开成功")cur=con.cursor()database:要连接的数据库的名称。user:用于身份验证的用户名,默认为“postgres”。password:用户的数据库密码,自己设置。host:数据库服务器的地址,如域名、“localhost”或IP地址。port:端口,默认值为5432。我们也可以使用sqlalchemy库进行连接,代码如下:fromsqlalchemyimportcreate_engineengine=create_engine('postgresql://postgres:password@localhost:5432/postgres')02、SQL数据库建表操作我们在Python中使用SQL语句CREATETABLE创建Postgres表,首先使用上面提到的方法建立数据库连接,然后调用属于连接对象的cursor()方法创建游标对象,用于实际执行命令。然后调用游标对象的execute()方法来帮助创建表。最后,我们需要提交con.commit()并关闭连接con.close()。“提交”连接告诉驱动程序将命令发送到数据库,这一步很重要。这里我们创建两个表,分别是“沪深300指数每日行情”和“沪深股票qfq每日行情”。importpsycopg2con=psycopg2.connect(database="postgres",user="postgres",password="",host="127.0.0.1",port="5432")print("数据库打开成功")cur=con.cursor()cur.execute("""CREATETABLE沪深300指数日线行情(ts_codeVARCHAR(10)NOTNULL,trade_dateDATENOTNULL,open_pNUMERICDEFAULT0,high_pNUMERICDEFAULT0,low_pNUMERICDEFAULT0,close_pNUMERICDEFAULT0,pre_closeNUMERICDEFAULT0,pct_chgNUMERICDEFAULT0,PRIMARYKEY(ts_code,trade_date));""")print("表创建成功")con.commit()con.close()简单来说,VARCHAR(10)、DATE、NUMERIC代表数据类型,NOTNULL代表非空约束,DEFAULT0代表默认值设置为0,PRIMARYKEY代表主键,用于唯一标识数据库表中的一行数据。如果看到如下输出,说明表创建成功。同样的方法,可以创建另一个表“沪深股票qfq日线行情”。DatabaseopenedsuccessfullyTablecreatedsuccessfullyinsertdata现在表已经创建成功,我们可以开始插入数据了。首先从tushare.pro获取沪深300指数每日行情数据,使用SQL语句INSERTINTO插入。importpsycopg2importpandasaspdimporttushareastscon=psycopg2.connect(database="postgres",user="postgres",password="",host="127.0.0.1",port="5432")print("数据库打开成功")cur=con.cursor()pro=ts.pro_api()df=pro.index_daily(ts_code='399300.SZ',start_date='20190501',end_date='20190531')#单位:涨跌幅(%),成交量(手),成交量(千))ts_code=df['ts_code'].tolist()trade_date=df['trade_date'].tolist()open_p=df['open'].tolist()high_p=df['high']。tolist()low_p=df['low'].tolist()close_p=df['close'].tolist()pre_close=df['pre_close'].tolist()pct_chg=df['pct_chg'].tolist()count=0foriinrange(len(ts_code)):cur.execute("""插入沪深300指数每日行情(ts_code,trade_date,open_p,high_p,low_p,close_p,pre_close,pct_chg)VALUES(%s,%s,%s,%s,%s,%s,%s,%s);""",(ts_code[i],trade_date[i],open_p[i],high_p[i],low_p[i],close_p[i],pre_close[i],pct_chg[i]))con.commit()print("已插入{0}行,一共{1}行".format(count,len(ts_code)))count+=1同理将tushare.pro中的沪深股票大盘数据插入“沪深股票qfq每日行情”表中。例子中只插入了两只股票,平安银行'000001.SZ'和万科A'000002.SZ'这里介绍另一种存储数据的方法,直接使用Pandas自带的df.to_sql(),插入将得到的DataFrame一次性存入数据库,比上面介绍的先建表再逐行插入的方法简单很多。fromsqlalchemyimportcreate_engineimportpandasasspdimporttushareaststs.set_token('yourtoken')engine=create_engine('postgresql://postgres:password@localhost:5432/postgres')print('数据库打开成功')pro=ts.pro_api()code_list=['000001.SZ','000002.SZ']foriincode_list:print(i)df=ts.pro_bar(ts_code=i,adj='qfq',start_date='20190501',end_date='20190531')df.to_sql(name='沪深stocksqfqDailyQuotes',con=engine,index=False,if_exists='append')值得注意的是,这种方法在数据量小的时候一般不会出问题,但是当数据量大的时候,可能会因为服务器无法响应而报错。这时候需要设置参数值chunksize来限制每次插入的行数。关于参数的更多说明,请参考官方文档[1]。有了数据,我们就可以使用SQL对数据库进行一系列的操作。获取数据,我们可以使用Pandas自带的.read_sql()方法获取数据,直接返回DataFrame格式,非常方便。详细的参数分析可以参考官方文档[2]。SQL的查询功能非常强大,下面介绍一些常用的过滤条件。选择表的特定列:fromsqlalchemyimportcreate_engineimportpandasasspdengine=create_engine('postgresql://postgres:password@localhost:5432/postgres')df_index=pd.read_sql("SELECTts_code,trade_date,close_pFROM沪深300指数每日行情;",con=engine)print(df_index.head())ts_codetrade_dateclose_p0399300.SZ2019-05-313629.78931399300.SZ2019-05-303641.18332399300.SZ2019-05-293663.90903399300.SZ2019-05-283672.26054399300.SZ2019-05-273637.1971用DISTINCT选取唯一值:df=pd.read_sql("SELECTDISTINCTts_codeFROM沪深股票qfq每日行情;",con=engine)print(df)ts_code0000001.SZ1000002.SZcountwithCOUNT:#查看一列有多少个唯一值df=pd.read_sql("SELECTCOUNT(DISTINCTts_code)FROM沪深股票qfq每日行情;",con=engine)print(df)count02使用WHERE语句筛选值:df=pd.read_sql("SELECT*FROM沪深股票qfq每日行情WHEREtrade_date='20190528';",con=engine)print(df)ts_codetrade_dateopen_p...close_ppre_closepct_chg0000001.SZ2019-05-2812.31...12.4912.370.971000002.SZ2019-05-2827.00...27.6227.002.3ORW和这里:df=pd.read_sql("SELECTts_code,trade_dateFROM沪深股票qfq每日行情WHERE(trade_date<'20190510'ORtrade_date>'20190520')ANDpct_chg>1;",con=engine)print(df)ts_codetrade_date0000001.SZ2019-05-211000002.SZ2012-00002.SZ2012-00002.SZ2019-05-07类似于WHERE语句,BETWEEN也可以与AND和OR一起使用:df=pd.read_sql("SELECTts_code,trade_dateFROM沪深股票qfq日线行情WHEREtrade_dateBETWEEN'20190510'AND'20190520'ANDpct_chg>1;",con=engine)print(df)ts_codetrade_date0000001.SZ2019-05-151000001.SZ2019-05-142000001.SZ2019-05-103000002.SZ2019-05-1540000002.SZ2019-05-1540000019.SZ2019-05-1540000019.SZ2019-05-1540000019.SZ2019-05-1540000019.SZ2019-05-1540000019WHERE和IN组合多个OR代码进行筛选:df=pd.read_sql("SELECTts_code,trade_dateFROM沪深股票qfq日行情WHEREtrade_dateIN('20190510','20190520','20190527');",con=engine)print(df)ts_codetrade_date0000001.SZ2019-05-271000001.SZ2019-05-202000001.SZ2019-05-103000002.SZ2019-05-274000002.SZ2019-05-205000002-0Z2019的意思空的ULISvalueISNOTNULL表示不是空值:df=pd.read_sql("SELECTCOUNT(*)FROM沪深股票qfq每日行情WHEREclose_pISNULL;",con=engine)print(df)count00可以使用聚合函数对数据做一些计算,比如平均值AVG(),最大值MAX(),求和SUM():df=pd.read_sql("SELECTAVG(close_p)FROMShanghaiand深300指数日盘;",con=engine)print(df)avg03659.63762聚合函数也可以结合WHERE语句进行过滤:df=pd.read_sql("SELECTAVG(close_p)FROM沪深300指数dailymarketWHEREtrade_date>'20190515';",con=engine)print(df)avg03645.740858用AS命名新列:df=pd.read_sql("""SELECTMAX(close_p)ASmax_close_p,MAX(open_p)ASmax_open_pFROMShanghaiand深300指数日盘;""",con=engine)print(df)max_close_pmax_open_p03743.96353775.0765ORDERBY排序,默认升序,降序需要在末尾加上DESC:#Ascendingorder:df=pd.read_sql("""SELECTts_code,trade_dateFROM沪深300指数日行情ORDERBYtrade_date;""",con=engine)print(df)#降序排列:df=pd.read_sql("""SELECTts_code,trade_dateFROM沪深300指数日行情ORDERBYtrade_dateDESC;""",con=engine)print(df)ORDERBY也可以按多列排序:df=pd.read_sql("""SELECTtrade_date,ts_codeFROM沪深股票qfq每日行情ORDERBYtrade_date,ts_code;""",con=engine)print(df)trade_datets_code02019-05-06000001.SZ12019-05-06000002.SZ22019-05-07000001.SZ32019-05-07000002.SZ42019-05-08000001.SZGROUPBY分组,并结合聚合函数分组计算数据:df=pd.read_sql(""SELECTts_code,COUNT(*)FROM沪深股票qfq每日行情GROUPBYts_code;""",con=engine)print(df)ts_codecount0000001.SZ201000002.SZ20如果要在分组GROUPBY的基础上添加聚合函数过滤条件,HAVING可以用:df=pd.read_sql("""SELECTts_codeFROM沪深股票qfq每日行情GROUPBYts_codeHAVINGCOUNT(*)>15;""",con=engine)print(df)ts_code0000001.SZ1000002.SZLIMIT来限制取行数:df=pd.read_sql("""SELECT*FROM沪深股票qfq每日行情LIMIT3;""",con=engine)print(df)ts_codetrade_dateopen_p...close_ppre_closepct_chg0000001.SZ2019-05-3112.16...12.1812.22-0.331000001.SZ2019-05-3012.32...12.2212.40-1.452000001.SZ2019-05-2912.36...12.4012.49-0.7203.总结本文介绍了数据库系统的优点,如何使用Python连接数据库,使用SQL是一种非常强大的查询语言进行后续的查询操作。在使用Python分析数据之前,可以通过过滤的方式准确获取想要的数据。Python和SQL的结合可以大大提高数据分析的效率和质量,希望大家能够学习和使用!