第22期:有序遍历语法

企业动态
遍历可以说是最基本的集合运算了,本篇文章我们将接上篇文章继续讨论遍历运算的语法规则。

 

【数据蒋堂】第22期:有序遍历语法

 

接前一期 【数据蒋堂】第21期:常规遍历语法

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

5. 序号的引用

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

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

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

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

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

  1. A.select(#<=A.len()/2)       取前一半成员 
  2. A.select(#%2==0)             取偶数位置的成员 

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

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

类似地,还可能有:

  1. A.pmax()                         返回***值的次序号 
  2. ... 

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

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

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

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

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

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

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

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

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

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

 

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

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

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

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

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

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

 

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

 

  1. A.select(销售额/销售额[-1]>1.05)                这里结果集中已有月份字段,不再需要用#了 
  2. A.derive(销售额[-1,1].avg:移动平均值)        增加一个字段表示移动平均 
  3. A.derive(销售额[,0].sum():累计销售额) 

 

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

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

责任编辑:赵宁宁 来源: 51CTO专栏
相关推荐

2017-09-05 22:34:24

遍历SQL运算

2017-10-09 22:33:56

SQL等值分组有序分组

2017-10-18 22:34:33

SQL等值分组有序分组

2017-12-26 15:33:24

JOINSQL运算

2018-01-10 15:25:43

JOIN维度SQL

2017-08-16 15:31:31

SQL语法集合化

2017-08-09 16:13:48

SQL大数据语法

2017-08-22 21:55:18

SQL语法离散性

2018-03-14 07:47:41

大数据语法SQL

2012-01-10 09:10:03

百度技术沙龙数据挖掘

2011-08-18 13:20:31

网络安全技术周刊

2009-11-17 15:07:16

PHP数组遍历

2013-01-24 10:20:28

桌面运维

2013-01-21 13:41:59

IBMdW

2016-05-18 14:34:34

2018-01-24 07:45:51

数据倍增分段列存

2018-01-18 20:47:18

CPU数据线程

2017-11-08 06:18:43

JOINSQL运算

2018-01-01 23:28:37

JOIN维度数据分析

2013-12-10 10:46:02

移动技术半月刊
点赞
收藏

51CTO技术栈公众号