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

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

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]                                     │
└─────────────────────────────────────────────────────┘

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

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会自动转换

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函数的方法不支持。

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,就把列表中多个值转成多行

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

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                                              │
├───────┼───────────────────────────────────────────────────────────────────────────────────────────────────┤
│     11*1=1                                                                                             │
│     21*2=2                                                                                             │
│     22*2=4                                                                                             │
│     31*3=3                                                                                             │
│     32*3=6                                                                                             │
│     33*3=9                                                                                             │
│     41*4=4                                                                                             │
│     42*4=8                                                                                             │
│     43*4=12                                                                                            │
│     44*4=16                                                                                            │
│     51*5=5                                                                                             │
│     52*5=10                                                                                            │
│     53*5=15                                                                                            │
│     54*5=20                                                                                            │
│     55*5=25                                                                                            │
├───────┴───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 15 rows                                                                                         2 columns │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────┘

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

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位宽左对齐,但注意格式符用单引号而不是双引号括起,双引号可以包括在单引号内原样输出。

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用行间列表运算输出杨辉三角

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] │
└───────┴─────────────────┘
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值