利用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] │
└───────┴─────────────────┘
相关推荐
老赵聊算法、大模型备案1 天前
北京市生成式人工智能服务已备案信息公告(2025年12月11日)
人工智能·算法·安全·aigc
CoderYanger1 天前
C.滑动窗口-求子数组个数-越长越合法——2799. 统计完全子数组的数目
java·c语言·开发语言·数据结构·算法·leetcode·职场和发展
廋到被风吹走1 天前
【数据库】【MySQL】InnoDB外键解析:约束机制、性能影响与最佳实践
android·数据库·mysql
厕所博士1 天前
红黑树原理前置理解—— 2-3 树
算法·2-3树·红黑树原理理解前置
掘根1 天前
【消息队列】交换机数据管理实现
网络·数据库
Logic1011 天前
《Mysql数据库应用》 第2版 郭文明 实验6 数据库系统维护核心操作与思路解析
数据库·sql·mysql·学习笔记·计算机网络技术·形考作业·国家开放大学
萌>__<新1 天前
力扣打卡每日一题————除自身外所有元素的乘积
数据结构·算法
AI Echoes1 天前
构建一个LangChain RAG应用
数据库·python·langchain·prompt·agent
xu_yule1 天前
算法基础—搜索(2)【记忆化搜索+BFS+01BFS+Floodfill]
数据结构·算法
s09071361 天前
Xilinx FPGA使用 FIR IP 核做匹配滤波时如何减少DSP使用量
算法·fpga开发·xilinx·ip core·fir滤波