Python3.因为不熟练SQL所以用pandas将表的一列按条件拆成若干列

2 篇文章 0 订阅

Python3.因为不熟练SQL所以用pandas将表的一列按条件拆成若干列

想在数据库中完成某个整理操作但是没弄出来,干脆导出来整理完再塞回去(可是我还是很想知道用SQL怎么实现啊)。需求是这样的:

station_namedate_data_codedata_
哥谭2003/1/1T_Day_Mean49
哥谭2003/1/1T_Day_Mean_2449
哥谭2003/1/1T_Day_Max110
哥谭2003/1/1T_Day_Min7
哥谭2003/1/1T_Day_Differ103
哥谭2003/1/1T_Day_Max_HourMinute32766
哥谭2003/1/1T_Day_Min_HourMinute32766
赛博坦2003/1/1T_Day_Mean50
赛博坦2003/1/1T_Day_Mean_2450
赛博坦2003/1/1T_Day_Max104
赛博坦2003/1/1T_Day_Min11
赛博坦2003/1/1T_Day_Differ93
赛博坦2003/1/1T_Day_Max_HourMinute32766
赛博坦2003/1/1T_Day_Min_HourMinute32766
阿斯加德2003/1/1T_Day_Mean53
阿斯加德2003/1/1T_Day_Mean_2453
阿斯加德2003/1/1T_Day_Max108
阿斯加德2003/1/1T_Day_Min3
阿斯加德2003/1/1T_Day_Differ105
阿斯加德2003/1/1T_Day_Max_HourMinute32766
阿斯加德2003/1/1T_Day_Min_HourMinute32766

要把上表[dbo].[TEM_temp]的data_列按照data_code列分成若干列到新表[dbo].[TEM],即变成每天每个站点只有一条记录,每条记录里除了站点名称、日期外有T_Day_Mean等7个温度指标,如下:

station_namedate_T_Day_MeanT_Day_Mean_24T_Day_MaxT_Day_MinT_Day_DifferT_Day_Max_HourMinuteT_Day_Min_HourMinute
哥谭2003/1/1494911071033276632766
赛博坦2003/1/1505010411933276632766
阿斯加德2003/1/1535310831053276632766

Python3代码如下

import pandas as pd
from sqlalchemy import create_engine

# 构造连接数据库的engine
userstr = 'UID:password@host/dbname'
linkstr = f'mssql+pyodbc://{userstr}?driver=SQL+Server'
con = create_engine(linkstr, encoding='utf-8')
# 数据全部读出来
sql = 'SELECT * FROM [dbo].[TEM_temp];'
old_frame = pd.read_sql(sql, con)
# 开始整理
# 按照data_code列拆出索要获得的某一字段
new_frame = old_frame[old_frame['data_code'] == 'T_Day_Mean'].copy()
del(new_frame['data_code'])  # 删掉data_code列
# 改列名
new_frame.rename(columns={'data_': 'T_Day_Mean', 
                          'history_record':'tem_history_record'}, inplace=True)
# 同理处理剩下的字段,并按照station_name和date_列merge到新表
fields = ['T_Day_Min', 'T_Day_Max', 'T_Day_Differ', 'T_Day_Min_HourMinute', 
          'T_Day_Max_HourMinute', 'T_Day_Mean_24']
for field in fields:
    temp = old_frame[old_frame['data_code'] == field].copy()
    temp.drop(columns=['data_code', 'history_record'], inplace=True)
    temp.rename(columns={'data_': field}, inplace=True)
    new_frame = new_frame.merge(temp, on=['station_id', 'station_name', 'date_'])  # merge到新表
# 整理下列的顺序
order = ['station_name',
         'date_',
         'T_Day_Mean',
         'T_Day_Min',
         'T_Day_Max',
         'T_Day_Differ',
         'T_Day_Min_HourMinute',
         'T_Day_Max_HourMinute',
         'T_Day_Mean_24',
         'history_record']
new_frame = new_frame[order]
# 塞回数据库
new_frame.to_sql('TEM', con, if_exists='replace', index=False)

然而我一开始用SQL整理时花了40多分钟,tempdb把剩余50G硬盘空间都用光最终还是失败了,报错“The transaction log for database ‘tempdb’ is full due to ‘ACTIVE_TRANSACTION’”。我的SQL脚本是这样的:

SELECT
    t1.station_name,
    t1.date_,
    t1.data_ AS T_Day_Mean,
    t2.data_ AS T_Day_Min,
    t3.data_ AS T_Day_Max,
    t4.data_ AS T_Day_Differ,
    t5.data_ AS T_Day_Min_HourMinute,
    t6.data_ AS T_Day_Max_HourMinute,
    t7.data_ AS T_Day_Mean_24,
    t1.tem_history_record
INTO
    [dbo].[TEM]
FROM
    [dbo].[TEM_temp] AS t1,
    [dbo].[TEM_temp] AS t2,
    [dbo].[TEM_temp] AS t3,
    [dbo].[TEM_temp] AS t4,
    [dbo].[TEM_temp] AS t5,
    [dbo].[TEM_temp] AS t6,
    [dbo].[TEM_temp] AS t7
WHERE
    t1.date_ = t2.date_
    AND t1.date_ = t3.date_
    AND t1.date_ = t4.date_
    AND t1.date_ = t5.date_
    AND t1.date_ = t6.date_
    AND t1.date_ = t7.date_
    AND t1.data_code = 'T_Day_Mean'
    AND t2.data_code = 'T_Day_Min'
    AND t3.data_code = 'T_Day_Max'
    AND t4.data_code = 'T_Day_Differ'
    AND t5.data_code = 'T_Day_Min_HourMinute'
    AND t6.data_code = 'T_Day_Max_HourMinute'
    AND t7.data_code = 'T_Day_Mean_24'
ORDER BY 3, 1;

好吧,就在写这篇傻文的时候,我发现我的SQL脚本里WHERE中忘记写

    t1.station_name = t2.station_name
    AND t1.station_name = t3.station_name
    AND t1.station_name = t4.station_name
    AND t1.station_name = t5.station_name
    AND t1.station_name = t6.station_name
    AND t1.station_name = t7.station_name
    AND 

忘记限制站点相同了,难怪之前费时费硬盘又失败。。。刚刚加上试了一下,只要14秒就跑出了正确的结果。。。我是个傻子。。。

不过仔细看一下发现了一点区别,[dbo].[TEM]中的data_是decimal(18,3)型数据,pandas读出来再写进去就变成了float型数据,而用SQL的话数据格式就没变,所以感觉还是SQL比较靠谱。

Anyway,我用两种方法都实现了我的这个简单需求。However,这两种方法感觉都比较复杂,尤其是SQL,我通过内联结给同一张表起了7个名字太傻了,应该有更简单的方式或者有更方便的SQL语句但是我不知道,究竟是时间会告诉我答案,还是大神会告诉我答案?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值