在python里面连接duckdb文件,从中读取多个表(同个schema或者多个schema),有2个常用的方法,方法1可以作为常用模板,特殊情况才用到方法2。
方法1 :拼接SQL后执行
import duckdb import polars as pl# duckdb的支持任意文件扩展名# 地址可以是本地 ,也可以是云端path_duckdb = r'/duckdb文件路径/duckdb文件.duckdb'connection = duckdb.connect(path_duckdb)# duckdb的层级 : database - > schema - > table# 连接到duckdb时,就默认指定了database , 因此从schema开始写即可# 单个和多个schema区别就是where中是 = 还是 in# 单个就是 = , 多个就是 in schema_单个 = r'表所在的schema'schema_多个 = ['表所在的schema_1','表所在的schema_2','表所在的schema_3']# 比如筛选年份为2026的表的筛选条件 = r'筛选年份为2026'# from 后面 必须跟着至少一个空格 , 不然sql语法错误# union all by name 前后 必须跟着至少一个空格 , 不然sql语法错误sql_聚合各表_单个schema = f""" select string_agg( 'from ' || table_schema || '.' || table_name , ' union all by name ' ) from information_schema.tables where table_schema = '{schema_单个}' and contains(table_name , '{表的筛选条件}')"""sql_聚合后的语句 = connection.execute(sql_聚合各表_单个schema).fetchone()[0]df_需要的表 = connection.execute(sql_聚合后的语句).pl()# 继续下一步操作
这里存在一个小问题:duckdb的表名字默认都会转成小写。
比如订单号字段,在 订单明细202601 是 order_id ,在 订单明细202602 是 Order_ID,用此种方法读取进来后会以前面的表字段名字为标准,即统一成 order_id 。
当需要确切字段名字的时候就会出现找不到字段的错误
实际案例 :跨境电商平台Tiktok_US ,下载的结算明细中有order_details和Reports 2个sheet ,相互匹配(或者与收入费用对照表匹配)的时候,当月匹配当月没问题 ,累计匹配的就会出现这个错误
方法2 :读取每张表后合并
此种方法是为了解决方法1存在的问题,先读取再合并,因为polars默认是大小写敏感的。
import duckdb import polars as pl# duckdb的支持任意文件扩展名# 地址可以是本地 ,也可以是云端path_duckdb = r'/duckdb文件路径/duckdb文件.duckdb'connection = duckdb.connect(path_duckdb)schema_单个 = r'表所在的schema'sql_需要的schema内所有表 = f""" select table_name from information_schema.tables where table_schema = '{schema_单个}' """list_所有表_元组形式 = connection.execute(sql_需要的schema内所有表).fetchall()dfs = []for 表 in list_所有表_元组形式: 提取表名字 = 表[0] sql_每个表 = f""" from {schema_单个}.{提取表名字} """ df_每个表 = connection.execute(sql_每个表).pl() dfs.append(df_每个表) df_合并所有表 = pl.concat(dfs,how='diagonal') # 继续其他操作