经常操作数据的同学们一定对序表这个名词很熟悉,从结构上来说跟数据库的表结构是类似的。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