查看原文
其他

数据蒋堂 | 有序遍历语法

2017-09-15 数据派THU

来源:数据蒋堂

作者:蒋步星

本文长度为800,建议阅读3分钟

本文为你介绍遍历运算中的有序遍历语法。


上一期数据蒋堂为你介绍遍历运算中的可能情况,并讨论SQL语法在这方面的表现:

数据蒋堂 | 常规遍历语法


这期我们将继续讨论遍历运算的语法规则。



5. 序号的引用


SQL延用了数学上的无序集合概念,遍历时也不关注次序。但计算机只能一步步地执行(暂先不考虑并行计算的情况),而遍历集合时总会有个次序,充分利用这个次序就可以方便地表达更丰富的计算需求。


比如我们想从一个集合取出半数成员构成新集合。这看起来象是过滤运算,但过滤条件和集合成员本身并没有关系,而是由遍历成员时的次序号决定的。


只有~写法无法方便地描述出这种运算,这时候还需有个符号(标识符)来表示遍历的次序号。


事实上,大部分高级语言在写循环语句时都会有个循环变量来表示次序号。但许多集合化语言中并没有提供这个机制,如果碰到这种运算就只能再写循环才能完成,如此就显得很繁琐。SQL也没有表示遍历次序后的方案,只能先用子查询人为制造一个序号出来,再针对这个序号进行过滤。


我们用#来表示遍历的次序号,那么这个运算就很容易写了:


A.select(#<=A.len()/2)       取前一半成员

A.select(#%2==0)             取偶数位置的成员


对应地,在过滤运算中我们总是返回满足条件的成员,但有时候我们并不关心具体成员而只关心成员的次序号,那么我们还有必要设计返回次序号的过滤函数:


A.pselect( ~>5 )            返回大于5的成员的次序号


类似地,还可能有:


A.pmax()                       返回最大值的次序号

...


6. 相邻成员和集合的引用


考虑到遍历的次序时,我们还可以进一步丰富计算的描述能力。


比如有个问题是“12个月的销售额数据已经按次序准备好,要计算哪些月份的增长率超过了5%”。


SQL很难写这种跨行计算,所以需要用JOIN语句或窗口函数把上月数据和本月数据对齐,然后再来计算增长率,这不可避免地用到子查询。


假设我们提供了相邻成员的引用语法,就可以很容易描述这个计算了。


比如用[i]表示和当前成员距离为i的成员,再结合前述的#写法,上面的计算就可以写成:


A.(if(~/~[-1]>1.05,#,0)).select(~>0)


~[-1]表示前一个成员,也就是上月销售额。找出把增长率超过5%的月份(也就是#),其它月份清0,最后选出这些非0的月份。


如果用上述的返回次序号的过滤函数,还可以写成更简单的形式:


A.pselect(~/~[-1]>1.05)


除了相邻成员外,还可能有相邻集合的引用。比如还是上面的集合,我们希望计算前后各一个月的销售额移动平均值。


把[i]表达式扩展成[a,b]写法来表示相邻成员构成的集合,这个运算就很容易描述了:


A.(~[-1,1].avg())


相邻集合还可能有更复杂的情况,比如计算到当月的累积销售额。


允许[a,b]写法中a缺省表示从第一个成员开始(对等地,b缺省可以理解为最后一个成员),这个运算可以写成


A.(~[,0].sum())


同样的,面向结构化数据计算也还可以直接使用字段名,比如如果例子中的集合是由“月份”和“销售额”的两个字段构成的表,则上述的运算可以分别写成:


A.select(销售额/销售额[-1]>1.05)      这里结果集中已有月份字段,不再需要用#了

A.derive(销售额[-1,1].avg:移动平均值)        增加一个字段表示移动平均

A.derive(销售额[,0].sum():累计销售额)



考虑到有序遍历时的语法规则就比常规遍历要复杂许多,并且这些有序遍历也是实际计算中经常发生的,如果遍历语法不支持,会导致这些计算难以描述,程序员就要再编写多行循环语句,繁琐且影响可读性。


SQL没有提供有序遍历的语法,经常需要使用子查询和窗口函数来生成序号,某些复杂些的有序遍历运算甚至写不出来,所以需要用存储过程手段转换成多行循环语句才可以。从这个意义讲,SQL虽然是集合化语言,但集合化不够彻底。


专栏作者简介


润乾软件创始人、首席科学家


清华大学计算机硕士,著有《非线性报表模型原理》等,1989年,中国首个国际奥林匹克数学竞赛团体冠军成员,个人金牌;2000年,创立润乾公司;2004年,首次在润乾报表中提出非线性报表模型,完美解决了中国式复杂报表制表难题,目前该模型已经成为报表行业的标准;2014年,经过7年开发,润乾软件发布不依赖关系代数模型的计算引擎——集算器,有效地提高了复杂结构化大数据计算的开发和运算效率;2015年,润乾软件被福布斯中文网站评为“2015福布斯中国非上市潜力企业100强”;2016年,荣获中国电子信息产业发展研究院评选的“2016年中国软件和信息服务业十大领军人物”;2017年, 自主创新研发新一代的数据仓库、云数据库等产品即将面世。


数据蒋堂


《数据蒋堂》的作者蒋步星,从事信息系统建设和数据处理长达20多年的时间。他丰富的工程经验与深厚的理论功底相互融合、创新思想与传统观念的相互碰撞,虚拟与现实的相互交织,产生出了一篇篇的沥血之作。此连载的内容涉及从数据呈现、采集到加工计算再到存储以及挖掘等各个方面。大可观数据世界之远景、小可看技术疑难之细节。针对数据领域一些技术难点,站在研发人员的角度从浅入深,进行全方位、360度无死角深度剖析;对于一些业内观点,站在技术人员角度阐述自己的思考和理解。蒋步星还会对大数据的发展,站在业内专家角度给予预测和推断。静下心来认真研读你会发现,《数据蒋堂》的文章,有的会让用户避免重复前人走过的弯路,有的会让攻城狮面对扎心的难题茅塞顿开,有的会为初入行业的读者提供一把开启数据世界的钥匙,有的甚至会让业内专家大跌眼镜,产生思想交锋。


往期回顾:

数据蒋堂 | 常规遍历语法

数据蒋堂 | 从SQL语法看离散性

数据蒋堂 | 从SQL语法看集合化

数据蒋堂 | SQL用作大数据计算语法好吗?

数据蒋堂 | SQL的困难源于关系代数

数据蒋堂 | SQL像英语是个善意的错误

数据蒋堂 | 开放的计算能力为数据库瘦身

数据蒋堂 | 计算封闭性导致臃肿的数据库

数据蒋堂 | 怎样看待存储过程的移植困难

数据蒋堂 | 存储过程的利之弊

数据蒋堂 | 不要对自助BI期望过高

数据蒋堂 | 报表的数据计算层

数据蒋堂 | 报表应用的三层结构

数据蒋堂 | 列式存储的另一面

数据蒋堂 | 硬盘的性能特征

数据蒋堂 | 我们需要怎样的OLAP?

数据蒋堂 | 1T数据到底有多大?

数据蒋堂 | 索引的本质是排序

数据蒋堂 | 功夫都在报表外--漫谈报表性能优化

数据蒋堂 | 非结构化数据分析是忽悠?

数据蒋堂 | 多维分析的后台性能优化手段


编辑:黄继彦

校对:朱江华峰


为保证发文质量、树立口碑,数据派现设立“错别字基金”,鼓励读者积极纠错

若您在阅读文章过程中发现任何错误,请在文末留言,或到后台反馈,经小编确认后,数据派将向检举读者发8.8元红包

同一位读者指出同一篇文章多处错误,奖金不变。不同读者指出同一处错误,奖励第一位读者。

感谢一直以来您的关注和支持,希望您能够监督数据派产出更加高质的内容。

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存