数据蒋堂 | 迭代聚合语法

来源:数据蒋堂

作者:蒋步星

本文长度为1200,建议阅读2分钟

本文为你解答想实现一个以前没有定义过的运算怎么办?是否可以用已有的语法和函数组合出来?


我们讨论过的常规聚合运算如SUM/COUNT和非常规聚合运算如maxp/top,都是事先设计好的聚合函数。但如果我们想实现一个以前没有定义过的运算怎么办?是否可以用已有的语法和函数组合出来?比如想做连乘运算,显然这也算是一种聚合。

(题外话:连乘可以用exp(SUM(ln(x)))来做,不过这有点耍赖了,而且这还对付不了成员是负数的情况。)

要设计这样的语法方案,我们来看看这些聚合结果值是如何被程序计算出来的。

SUM:先设置一个初始值0,然后遍历集合的每个成员,每次将成员值加到初始值上,直到成员被遍历完。

COUNT:设置初始值0,遍历集合成员,每次碰到非空成员将初始值加1,直到遍历完。

AVERAGE:这个不能边遍历边计算了,不过AVERAGE=SUM/COUNT,算是个导出函数,不用考察了。

MAX:设置初始值为无穷小,遍历集合成员,每碰比初始值更大的成员值则替换初始值,直到遍历完。

MIN:和MAX一样,只是初始值和比较方向是反的。

我们发现,这些基本聚合运算的实现方案都有相同的过程:先设置一个初始值,然后遍历集合成员,让当前成员和初始值计算得到一个新的初始值,再进入下一轮循环,直到遍历完整个集合,那个初始值就变成我们需要聚合值了。

这样,我们可以设计一个实现迭代计算的聚合函数:

A.iterate( x, a )

以a为初始值遍历集合A,每次用当前初始值和当前遍历员计算表达式x,得到的结果替换当前初始值,直到遍历完成,返回最后的x值。

这里有个问题,在x中用什么标识符或符号来表示当前初始值和当前成员。当前成员可以用我们以前讨论过的~符号,当前初始值要再找个符号,我们用两个~来表示。

这样,前面那些聚合运算就都可以用这个迭代函数来表示:

A.SUM() = A.iterate( ~~+~, 0 )

A.COUNT() = A.iterate( ~+if(~~,1,0),0 )

A.MAX() = A.iterate( if(~>~~,~,~~), -inf )

A.MIN() = A.iterate( if( ~<~~,~,~~), inf )

连乘当然也很简单了:A.iterate( ~~*~, 1 )

我们提到过的非常规聚合也可以,比如返回单值的maxp可以写成

A.maxp(F) = A.iterate( if (~==null || ~.F>>~~.F,~,~~), null )       这是F表示字段名

但返回集合的情况要麻烦一些:

A.maxp(F) = A.iterate( if(~==null || ~.F>~~.F,~,if(~.F==~~.F,~~|~,~~)), null )       |表示集合的并运算

A.top( n ) = A.iterate( merge(~~,~).to(n), [inf]*n )        merge函数指归并排序运算,to(n)选出集合的前n个成员

A.distinct() = A.iterate( if(~~.contain(~),~,~~|~), [] )         contain函数判断集合是否包含某成员

不过,不是所有的聚合运算都容易用iterate来描述,毕竟聚合运算的定义太宽泛了,比如中位数就不合适用itertate描述。另外,象first/last这种聚合运算不需要遍历,也没必要用iterate描述。

迭代聚合语法不但能够帮助我们写出一些新的聚合运算,而且它本身就是一种遍历方法。能用迭代语法写出来的聚合运算,都可以一边遍历一边计算,遍历完了就得到聚合值,目标集合只需要遍历一次。

我们知道,计算机不能直接针对外存计算,当数据量很大而不能全部加载进内存时,迭代聚合算法可以只需要较小的内存(能够放下聚合值)就可以完成大数据量的聚合。这对于实现分组后的聚合运算很有意义。

分组子集的总体数据规模和原集是一样大的,基于拆分后的子集再做聚合运算就意味着要遍历两次,对于纯内存运算还不是大问题,但如果数据量大到内存放不下时,就会发生外存倒换的现象,这样效率是非常低的。iterate作为一种聚合运算当然可以用在分组之后,分组后进行能够被iterate描述的聚合运算时,就不需要对原数据遍历两次了,可以一边分组一边聚合,只需要较小的内存(能保存下结果集)就可以完成。

这大概也是SQL没有提供分组子集的原因之一,在发明SQL的那个年代内存很小,绝大多数原始数据都不可能放入内存,先产生分组子集后再聚合的运算效率难以容忍,而分组后直接聚合,且都是可以用iterate描述的聚合,虽然仍然可能发生外存倒换(结果集也装不下内存时)的现象,但问题的严重程度要小很多。


专栏作者简介

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


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


数据蒋堂


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


往期回顾:

数据蒋堂 | 非常规聚合

数据蒋堂 | 再谈有序分组

数据蒋堂 | 有序分组

数据蒋堂 | 非等值分组

数据蒋堂 | 还原分组运算的本意

数据蒋堂 | 有序遍历语法

数据蒋堂 | 常规遍历语法

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


校对:朱江华峰

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

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值