利用DuckDB列表一句SQL输出乘法口诀表

先热身,用生成式列表输出几行不同长度的序列,从默认的标题列可知,生成式列表后台实际调用了list_apply函数。

sql 复制代码
D select [i for i in range(1,a+1)]from range(1,6)t(a);
┌─────────────────────────────────────────────────────┐
│ main.list_apply("range"(1, (a + 1)), (lambda i: i)) │
│                       int64[]                       │
├─────────────────────────────────────────────────────┤
│ [1]                                                 │
│ [1, 2]                                              │
│ [1, 2, 3]                                           │
│ [1, 2, 3, 4]                                        │
│ [1, 2, 3, 4, 5]                                     │
└─────────────────────────────────────────────────────┘

再把生成式的结果表达式变为字符串连接

sql 复制代码
D select [i::text||'*'||a::text||'='||(i*a)::text for i in range(1,a+1)]from range(1,6)t(a);
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ main.list_apply("range"(1, (a + 1)), (lambda i: ((((CAST(i AS VARCHAR) || '*') || CAST(a AS VARCHAR)) || '=') || C...  │
│                                                      varchar[]                                                       │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ['1*1=1']                                                                                                            │
│ ['1*2=2', '2*2=4']                                                                                                   │
│ ['1*3=3', '2*3=6', '3*3=9']                                                                                          │
│ ['1*4=4', '2*4=8', '3*4=12', '4*4=16']                                                                               │
│ ['1*5=5', '2*5=10', '3*5=15', '4*5=20', '5*5=25']                                                                    │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

其中的强制转换可以省略,DuckDB会自动转换

sql 复制代码
D select [i||'*'||a||'='||(i*a) for i in range(1,a+1)]from range(1,6)t(a);
┌───────────────────────────────────────────────────────────────────────────────────────────┐
│ main.list_apply("range"(1, (a + 1)), (lambda i: ((((i || '*') || a) || '=') || (i * a)))) │
│                                         varchar[]                                         │
├───────────────────────────────────────────────────────────────────────────────────────────┤
│ ['1*1=1']                                                                                 │
│ ['1*2=2', '2*2=4']                                                                        │
│ ['1*3=3', '2*3=6', '3*3=9']                                                               │
│ ['1*4=4', '2*4=8', '3*4=12', '4*4=16']                                                    │
│ ['1*5=5', '2*5=10', '3*5=15', '4*5=20', '5*5=25']                                         │
└───────────────────────────────────────────────────────────────────────────────────────────┘

字符串列表形式的输出不美观,可以转换为纯字符串。listagg函数直接嵌套unnest函数的方法不支持。

sql 复制代码
D select listagg(unnest([i||'*'||a||'='||(i*a) for i in range(1,a+1)])) from range(1,6)t(a);
Binder Error:
UNNEST not supported here

LINE 1: select listagg(unnest([i||'*'||a||'='||(i*a) for i in range(1,a+1)])) from...
                       ^

但是可以单独对列表unnest,就把列表中多个值转成多行

sql 复制代码
D select unnest([i||'*'||a||'='||(i*a) for i in range(1,a+1)]) from range(1,6)t(a);
┌───────────────────────────────────────────────────────────────────────────────────────────────────┐
│ unnest(main.list_apply("range"(1, (a + 1)), (lambda i: ((((i || '*') || a) || '=') || (i * a))))) │
│                                              varchar                                              │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 1*1=1                                                                                             │
│ 1*2=2                                                                                             │
│ 2*2=4                                                                                             │
│ 1*3=3                                                                                             │
│ 2*3=6                                                                                             │
│ 3*3=9                                                                                             │
│ 1*4=4                                                                                             │
│ 2*4=8                                                                                             │
│ 3*4=12                                                                                            │
│ 4*4=16                                                                                            │
│ 1*5=5                                                                                             │
│ 2*5=10                                                                                            │
│ 3*5=15                                                                                            │
│ 4*5=20                                                                                            │
│ 5*5=25                                                                                            │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│                                              15 rows                                              │
└───────────────────────────────────────────────────────────────────────────────────────────────────┘

还可以带上原来的列a

sql 复制代码
D select a,unnest([i||'*'||a||'='||(i*a) for i in range(1,a+1)]) from range(1,6)t(a);
┌───────┬───────────────────────────────────────────────────────────────────────────────────────────────────┐
│   a   │ unnest(main.list_apply("range"(1, (a + 1)), (lambda i: ((((i || '*') || a) || '=') || (i * a))))) │
│ int64 │                                              varchar                                              │
├───────┼───────────────────────────────────────────────────────────────────────────────────────────────────┤
│     1 │ 1*1=1                                                                                             │
│     2 │ 1*2=2                                                                                             │
│     2 │ 2*2=4                                                                                             │
│     3 │ 1*3=3                                                                                             │
│     3 │ 2*3=6                                                                                             │
│     3 │ 3*3=9                                                                                             │
│     4 │ 1*4=4                                                                                             │
│     4 │ 2*4=8                                                                                             │
│     4 │ 3*4=12                                                                                            │
│     4 │ 4*4=16                                                                                            │
│     5 │ 1*5=5                                                                                             │
│     5 │ 2*5=10                                                                                            │
│     5 │ 3*5=15                                                                                            │
│     5 │ 4*5=20                                                                                            │
│     5 │ 5*5=25                                                                                            │
├───────┴───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 15 rows                                                                                         2 columns │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────┘

用listagg访问子查询就可以了,注意要针对列a排序

sql 复制代码
D select listagg(b,' ') from(select a,unnest([i||'*'||a||'='||(i*a) for i in range(1,a+1)])b from range(1,6)t(a))group by a;
┌───────────────────────────────────┐
│          listagg(b, ' ')          │
│              varchar              │
├───────────────────────────────────┤
│ 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 │
│ 1*1=1                             │
│ 1*4=4 2*4=8 3*4=12 4*4=16         │
│ 1*3=3 2*3=6 3*3=9                 │
│ 1*2=2 2*2=4                       │
└───────────────────────────────────┘
D select listagg(b,' ') from(select a,unnest([i||'*'||a||'='||(i*a) for i in range(1,a+1)])b from range(1,6)t(a))group by a order by a;
┌───────────────────────────────────┐
│          listagg(b, ' ')          │
│              varchar              │
├───────────────────────────────────┤
│ 1*1=1                             │
│ 1*2=2 2*2=4                       │
│ 1*3=3 2*3=6 3*3=9                 │
│ 1*4=4 2*4=8 3*4=12 4*4=16         │
│ 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 │
└───────────────────────────────────┘

上述输出随着数字变大,算式变长,没有对齐,可以用printf函数格式化,函数的格式符按照C语言的标准格式,-8表示8位宽左对齐,但注意格式符用单引号而不是双引号括起,双引号可以包括在单引号内原样输出。

sql 复制代码
D select listagg(printf('%-8s',b),' ') from(select a,unnest([i||'*'||a||'='||(i*a) for i in range(1,a+1)])b from range(1,6)t(a))group by a order by a;
┌──────────────────────────────────────────────┐
│       listagg(printf('%-8s', b), ' ')        │
│                   varchar                    │
├──────────────────────────────────────────────┤
│ 1*1=1                                        │
│ 1*2=2    2*2=4                               │
│ 1*3=3    2*3=6    3*3=9                      │
│ 1*4=4    2*4=8    3*4=12   4*4=16            │
│ 1*5=5    2*5=10   3*5=15   4*5=20   5*5=25   │
└──────────────────────────────────────────────┘

D select printf('Benchmark "%s" took %d seconds', 'CSV', 42);
┌─────────────────────────────────────────────────────┐
│ printf('Benchmark "%s" took %d seconds', 'CSV', 42) │
│                       varchar                       │
├─────────────────────────────────────────────────────┤
│ Benchmark "CSV" took 42 seconds                     │
└─────────────────────────────────────────────────────┘

以下是结合递归CTE用行间列表运算输出杨辉三角

sql 复制代码
D with recursive t as(select 1 lv, [1]y union all select lv+1,[case when i=1 or i=lv+1 then 1 else y[i-1]+y[i] end for i in range(1, lv+2)] from t where lv <5 )from t;
┌───────┬─────────────────┐
│  lv   │        y        │
│ int32 │     int32[]     │
├───────┼─────────────────┤
│     1 │ [1]             │
│     2 │ [1, 1]          │
│     3 │ [1, 2, 1]       │
│     4 │ [1, 3, 3, 1]    │
│     5 │ [1, 4, 6, 4, 1] │
└───────┴─────────────────┘
相关推荐
chilavert3181 分钟前
技术演进中的开发沉思-299 计算机原理:数据结构
算法·计算机原理
C+-C资深大佬9 分钟前
C++逻辑运算
开发语言·c++·算法
汽车仪器仪表相关领域11 分钟前
光轴精准测量,安全照明保障——NHD-8101/8000型远近光检测仪项目实战分享
数据库·人工智能·安全·压力测试·可用性测试
大爱编程♡21 分钟前
Spring IoC&DI
数据库·mysql·spring
天天进步201522 分钟前
KrillinAI 源码级深度拆解二:时间轴的艺术:深入 KrillinAI 的字幕对齐与音频切分算法
算法·音视频
爱编程的小吴23 分钟前
【力扣练习题】121. 买卖股票的最佳时机
算法·leetcode·职场和发展
生信大杂烩25 分钟前
空间转录组分析新工具 | MEcell:自适应微环境感知建模,精准解析细胞身份!
算法·数据分析
king_harry30 分钟前
金仓数据库KingbaseES中WalMiner接口使用
数据库·kingbase·walminer
kaikaile199531 分钟前
计算向量x的功率谱密度
算法
爱潜水的小L34 分钟前
自学嵌入式day43,商城网页
数据库·oracle