经常操作数据的同学们一定对序表这个名词很熟悉,从结构上来说跟数据库的表结构是类似的。tinyscript的序表是非常实用的数据结构,不仅可以处理数据库,也可以处理excel、文本文档等其他存储方式。相对序列而言,序表具有横纵两个维度,更适合表现固定结构的有序数据。
提到固定有序的数据结构,很多人第一印象就是通过sql查询出来的表数据,的确数据库使用的场景太多了,但是它的缺点也是很明显:
- 多表关联sql很复杂,不支持集合运算
- 无法对查询结果二次加工
- 不支持其他数据源
而这些tinyscript的序表都能很简单实现,无需用户额外编码。
比如说实现A/B两表的关联:
ds1 = [[ SELECT * from A ]].toDynamic();
ds2 = [[ SELECT * from B ]].toDynamic();
//测试内联
inner = ds1.join(ds2,"userid=userid");
println(inner);
println("=================================");
//测试左联
left = ds1.leftjoin(ds2,"userid=userid");
println(left);
println("=================================");
//测试右联
right = ds1.rightjoin(ds2,"userid=userid");
println(right);
println("=================================");
//测试全联
full = ds1.fulljoin(ds2,"userid=userid");
println(full);
println("=================================");
输出结果如下:
userid username password userid jifen dengji
1 jack jackpwd 1 20 3
=================================
userid username password userid jifen dengji
1 jack jackpwd 1 20 3
2 open openpwd null null null
=================================
userid username password userid jifen dengji
1 jack jackpwd 1 20 3
null null null 3 50 6
=================================
userid username password userid jifen dengji
1 jack jackpwd 1 20 3
2 open openpwd null null null
null null null 3 50 6
=================================
在tinyscript中序表结构是可以二次编辑的,无论是新增列还是修改记录内容,方便用户二次开发,无需把所有逻辑放到sql语句里面完成。
//序表新建UP列,将CL列的值转换double类型,按CODE字段进行分组,分组内部按DT字段进行升序排列
groupds =ds.insertColumn("UP").double("CL").group("CODE").sortGroup("DT ASC"); //链式命令风格
groupds.update("UP",0d); //更新UP列的结果为0
groupds.update("UP",(CL[0]-CL[-1])/CL[-1]); //之后的每天统计当天的涨停率。
通过join命令或者match命令,用户可以将两个序表进行关联操作,无论它们是否隶属相同数据源。tinyscript的序表操作与数据源无关,这就使得用户操作更加方便。
序表也支持集合操作(差、并、交、异或),假设我们有如下两个序表:
dataSet1 = readTxt("/dataSetExample/data1.txt");
dataSet2 = readTxt("/dataSetExample/data2.txt");
println(dataSet1);
println("================================================================");
println(dataSet2);
println("================================================================");
我们可以了解这两个序表的结构如下:
name weight value count
a 2 6 1
b 2 3 1
c 6 5 1
e 4 6 1
d 5 4 1
================================================================
name weight value count
a 2 6 1
b 1 3 1
r 6 5 1
f 5 4 1
e 4 6 1
================================================================
执行序表交集运算
result = dataSet1.intersect(dataSet2,()->{ return name+"|"+weight; });
println(result);
println("================================================================");
result = dataSet1.intersect(dataSet2,["name","weight"]);
println(result);
println("================================================================");
结果如下:
name weight value count
a 2 6 1
e 4 6 1
================================================================
name weight value count
a 2 6 1
e 4 6 1
================================================================
执行序表并集运算
result = dataSet1.unite(dataSet2,()->{ return name+"|"+weight; });
println(result);
println("================================================================");
result = dataSet1.unite(dataSet2,["name","weight"]);
println(result);
println("================================================================");
结果如下:
name weight value count
a 2 6 1
b 2 3 1
c 6 5 1
e 4 6 1
d 5 4 1
b 1 3 1
r 6 5 1
f 5 4 1
================================================================
name weight value count
a 2 6 1
b 2 3 1
c 6 5 1
e 4 6 1
d 5 4 1
b 1 3 1
r 6 5 1
f 5 4 1
================================================================
执行差运算
result = dataSet1.subtract(dataSet2,()->{return name+"|"+weight;});
println(result);
println("================================================================");
result = dataSet1.subtract(dataSet2,["name","weight"]);
println(result);
println("================================================================");
结果如下:
name weight value count
b 2 3 1
c 6 5 1
d 5 4 1
================================================================
name weight value count
b 2 3 1
c 6 5 1
d 5 4 1
================================================================
当然序表的分组聚合也是支持,tinyscript设计了三种分组方式:字段分组、静态条件分组和动态条件分组
首先访问数据库获取表结构信息:
defaultDB = "mysql";
d = dynamicDataSource[[ select * from test2 ]].toDynamic();
println(d);
test2信息如下:
ID FULLNAME AGE SEX
1 莫小二 20 2
2 张大名 30 1
3 李德宏 78 2
4 赵方毅 45 1
5 John 12 1
6 冯若依曼 45 1
7 Tom 12 1
8 赵真 45 2
9 邱少云 30 1
10 王三 12 2
字段分组是最简单的分组方式,可以说通过sql也可以实现,是最基本常用的分组。
//按年龄和性别分组
println(d.group("age","sex").select("id","fullname"));
结果如下:
----------------------------------------
ID FULLNAME
----------------------------------------
1 莫小二
----------------------------------------
2 张大名
9 邱少云
----------------------------------------
3 李德宏
----------------------------------------
4 赵方毅
6 冯若依曼
----------------------------------------
5 John
7 Tom
----------------------------------------
8 赵真
----------------------------------------
10 王三
----------------------------------------
可以看出具有相同年龄和性别的记录分成一组,这也和sql操作结果一致。但是tinyscript的采用链式风格,不用一次性输出全部逻辑,可以通过命令组合降低业务的难度。
第二种分组是静态条件分组,用户输入一组布尔表达式做条件,假设有N个条件,最多输出N+1个分组(其中不匹配所有条件的记录自己成为一组。)
println(d.groupStaged(AGE<=18,AGE>=18 && AGE <60 , AGE>=60));
结果如下:
----------------------------------------
ID FULLNAME AGE SEX
----------------------------------------
5 John 12 1
7 Tom 12 1
10 王三 12 2
----------------------------------------
1 莫小二 20 2
2 张大名 30 1
4 赵方毅 45 1
6 冯若依曼 45 1
8 赵真 45 2
9 邱少云 30 1
----------------------------------------
3 李德宏 78 2
----------------------------------------
这种使用场景一般是有业务条件,特别适合if/elseif这种的情况
最后一种情况是动态条件分组,用户输入一个计算表达式,按计算结果的不同进行分组,理论上分组可以是变化的。
println(d.groupDynamic(ID%5));
结果如下:
----------------------------------------
ID FULLNAME AGE SEX
----------------------------------------
5 John 12 1
10 王三 12 2
----------------------------------------
1 莫小二 20 2
6 冯若依曼 45 1
----------------------------------------
2 张大名 30 1
7 Tom 12 1
----------------------------------------
3 李德宏 78 2
8 赵真 45 2
----------------------------------------
4 赵方毅 45 1
9 邱少云 30 1
----------------------------------------
无论静态条件分组还是动态条件分组,都是sql语句很难实现的功能,这也是tinyscript的强大所在。
小结:
当然序表的功能远不止这一点,碍于篇幅就不能逐一介绍了。tinyscript的序表核心想法是通过链式命令操作,拆分业务逻辑,从而降低整体业务难度;屏蔽底层数据源差异,刚才例子也可以看到我们引用了数据库、文件和csv多种数据源,这样使得用户可以专注于业务逻辑的实现而非底层细节。
更详细的序表功能,用户可以访问tiny的官方论坛获取,相信你一旦用上序表,就会爱上它强大的功能。
tinyscript开源地址:
https://gitee.com/tinyframework/tinyscript.git