在使用阿里maxcomputer进行数据库查询过程中,当查询结果超过一万行时无法直接导出csv文件,解决方法比较多:
1、MaxCompute Studio的基础平台IntelliJ IDEA,将查询结果写入临时表中,在客户端进行导出
(阿里教程:https://help.aliyun.com/document_detail/50891.html?spm=5176.10695662.1996646101.searchclickresult.3dc41598EQEYGm&aly_as=Vu68vGZA);
2、安装Navicat Premium(可链接多个数据库的管理工具),查询并导出;
3、其他。
因为嫌安装和配置软件比较麻烦,且最近在学习python,所以想练习下,写代码实现将查询结果直接写入Excel中。
本文仅作为自己的学习记录。
python集成开发环境:pycharm
Python版本: Python3.7
ODPS:第三方库,连接maxcomputer查询数据
openpyxl:第三方库,处理xlsx格式的Excel文件
datetime:处理时间
1、第一次接触odps,不太会o(╥﹏╥)o。引用知乎上周田的回答:pyodps提供了用python去操作odps的接口,你可以用你熟悉的python与odps交互,操作odps上的表、任务、函数、资源等。pyodps说明文档:https://pyodps.readthedocs.io/zh_CN/latest/?spm=a2c4g.11186623.2.2.OXF9Bx
2、在将sql查询结果写入Excel时,因含有反斜杠等特殊字符导致写入失败,故需要进行处理,我用的方法比较笨,用遍历sql查询结果将特殊字符替换为空的方式来实现的,总之是达到目的了,毕竟目前是小白,先实现效果再说。
下面定义了三个基本功能模块,分别是连接odps,异常字符串处理,写入Excel
from odps import ODPS
#链接odps
o = ODPS(access_id='xxxxxxx', #登陆账号
secret_access_key='xxxxxxxx', #登陆密码
project='xxxxxx', #odps上的项目名称
endpoint='http://service.odps.aliyun.com/api') #官方提供的接口
#定义处理非法字符的方法
def illegal_char_rm(l):
la = list()
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE
for record in l: #遍历每条表记录
for index,value in enumerate(record.values): #遍历记录的每一列的值,record.values类型为list,取list的index和value需要用enumerate,不然会报错
record[index]=ILLEGAL_CHARACTERS_RE.sub('', value) if isinstance(value,str) else value #如果值类型为字符串,替换为空,否则保留原值
la.append(record)
return la
#定义写Excel的方法
def write_excel(workbook_name,sheet_name,data):
data = illegal_char_rm(data) #写入前进行非法字符处理
import openpyxl
workbook = openpyxl.Workbook() #创建工作簿workbook
sheet = workbook.active #创建工作表sheet,默认使用active页
sheet.title = sheet_name #给工作表赋名
sheet.append(list(data[0]._name_indexes.keys())) #取sql查询结果的字段名
for record in data:
sheet.append(record.values) #取每条记录
workbook.save(workbook_name) #保存工作薄并命名
下面是将我在工作中用两种方式获取的数据导入Excel的方法
方法一:
#定义用sql查询结果写入Excel方法
def write_excel_form_sql(workbook_name,sheet_name,sql):
#定义查询语句的分区参数(取昨日)
import datetime
ds = (datetime.datetime.now() + datetime.timedelta(days=-1)).strftime('%Y%m%d')
sql = sql.replace('${bdp.system.bizdate}', ds)
#读取查询记录
instance = o.execute_sql(sql)
reader =instance.open_reader()
#写入表格
write_excel(workbook_name,sheet_name,reader)
#将sql临时查询结果写入Excel
workbook_name=r'E:\test'+'.xlsx' #这里可以定义存储路径,不要忘了前边的r,即保留字符串,反斜杠不转义
sheet_name='maydata'
sql = '''
SELECT user_id 用户id
,wechat_name 微信昵称
,user_name 用户名字
FROM dim_user u
WHERE u.ds = '${bdp.system.bizdate}' --系统参数。定义为一个实例运行时对应的业务日期,业务日期默认为运行日期的前一天,默认以 yyyymmdd 的格式显示。
'''
write_excel_form_sql(workbook_name,sheet_name,sql)
方法二:
#定义将odps中已存在的表写入Excel方法
def write_excel_form_odpstable(workbook_name,sheet_name,odps_table_name):
data = [value for value in o.read_table(odps_table_name)]
write_excel(workbook_name,sheet_name,data)
#将odps中已存在的表写入Excel方法
workbook_name=r'E:\test'+'.xlsx' #这里可以定义存储路径,不要忘了前边的r,即保留字符串,反斜杠不转义
sheet_name='aa'
#将odps中已存在的表写入Excel
odps_table_name='table_name' #odps中已存在的表的名字,没有分区的
write_excel_form_odpstable(workbook_name,sheet_name,odps_table_name)