假定存在如下电子表格
D from read_sheet('n1.et');
┌───────┬───────┐
│ C1 │ C2 │
│ int64 │ int64 │
├───────┼───────┤
│ 1 │ 2 │
└───────┴───────┘
D from read_sheet('n2.et');
┌───────┬───────┐
│ C1 │ C3 │
│ int64 │ int64 │
├───────┼───────┤
│ 1 │ 3 │
└───────┴───────┘
希望两个文件合并后显示如下,即同名的列显示在一列,如果某个列在某个文件中不存在,则显示NULL,这在DuckdDB中称作union by name。
D from read_sheet('n1.et') union by name from read_sheet('n2.et');
┌───────┬───────┬───────┐
│ C1 │ C2 │ C3 │
│ int64 │ int64 │ int64 │
├───────┼───────┼───────┤
│ 1 │ 2 │ NULL │
│ 1 │ NULL │ 3 │
└───────┴───────┴───────┘
现在rusty_sheet插件尚不支持多个xlsx文件自动union by name,所以要手工编写SQL,如果文件很多,复制粘贴很乏味也容易出错,能否用SQL编程实现。
其实可以,如下的SQL就可以实现输出上述union by name的SQL。
D select 'from read_sheet('''||file||case when row_number()over()<> count()over()then ''') union by name' else ''');' end as " " from glob('n*.et');
┌────────────────────────────────────────┐
│ │
│ varchar │
├────────────────────────────────────────┤
│ from read_sheet('n1.et') union by name │
│ from read_sheet('n2.et'); │
└────────────────────────────────────────┘
但是要把SQL语句从输出中复制粘贴执行仍然很乏味也容易出错。
方法1
使用.output将结果重定向到脚本文件,然后执行此文件
load '/par/rusty_sheet.duckdb_extension';
.header off
.mode list
.output script.sql
select 'from read_sheet('''||file||case when row_number()over()<> count()over()then ''') union by name' else ''');' end from glob('n*.et');
.output
.header on
.mode duckbox
.read script.sql
方法2,在操作系统命令行使用管道操作
./duckdb141 -list -c "select 'from read_sheet('''||file||case when row_number()over()<> count()over()then ''') union by name' else ''');' end as \" \" from glob('n*.et')" | ./duckdb141 -unsigned -cmd "load '/par/rusty_sheet.duckdb_extension'"
管道符前的部分也可以用-cmd来消除标题行, 就不必写as \" \" 用空格做标题了。
duckdb141 -list -cmd ".header off" -c "select 'from read_sheet('''||file||case when row_number()over()<> count()over()then ''') union by name' else ''');' end from glob('n*.et')"
这两种方法都能实现自动对多个xlsx文件union by name。


被折叠的 条评论
为什么被折叠?



