迟来的主角
窗口函数可以说是本书的主角,但从SQL的历史来看,它是最近才出现的。窗口函数在20世纪90年代后半期开始被引入到标准SQL中,而主流DBMS从21世纪才开始支持窗口函数,MySQL甚至到了2017年才宣布支持窗口函数。
窗口函数年表:
| 年份 | 事件 |
|---|---|
| 1999 | Oracle8i和DB2 UDB7.1支持(部分)面向OLAP的窗口函数。甲骨文和IBM公司一起向ANSI提议标准化,SQL:1999中将其采纳为可选项。 |
| 2003 | SQL:2003中全面实现标准化 |
| 2005 | 微软公司的SQL Server2005支持窗口函数 |
| 2009 | PostgreSQL8.4支持窗口函数 |
| 2011 | SQL:2011中,帧子句实现标准化 |
| 2017 | MySQL8.0.11(GA)支持窗口函数 |
| 窗口函数为什么这么晚才出现呢? | |
| 窗口函数的内部实现只是对记录进行排序,不需要很复杂的逻辑,本书的第一章已经介绍过其无与伦比的便捷性。既然如此,为什么不在SQL发展的早期就实现它呢?如果从一开始就可以使用窗口函数,不依赖关联子查询和自连接等复杂的工具(在不了解集合论背景的大多数用户看来),那么被SQL难住的工程师肯定会非常少吧。 | |
| 其中一个原因是,对于基本不使用数据库进行数据分析的人来说,其实并不需要通过窗口函数实现的统计处理功能。OLAP被称为当今大数据分析的先锋,其构想始于20世纪80年代,从20世纪90年代开始市场需求上升,相应的DWH专用的DBMS和BI工具也开始相继出现。没有需求就没有发明,说的就是这个道理。 | |
| 还有另外一个原因,关系数据库和SQL成功建立了相当严密的数学基础,所以意识形态方面比其他编程语言更加突出。 |
行应该有顺序吗
关系数据库和SQL旨在去掉“数据位置”这种低层次的概念,表达高度抽象的数据。因此,“行的顺序”也就成了被攻击的对象。关系数据库中表的定义不包含行的顺序,SQL编码也不使用行的顺序,否则会被认为是“未摆脱面向过程思想的错误做法”。另外,带循环的PSM(即所谓的存储过程)之所以被认为不像是SQL的做法,也是因为这个原因。
n元关系被选为关系模型唯一的集合结构,是因为使用合适的运算符和概念表达式(表)可以实现前面讲述的3个目的。请注意,n元关系是数学集合,行的顺序是非本质的。
传统主义保守派的主张
尽管科德并没有强烈地否定行的顺序,但后来的工程师们似乎有了不同的想法。IBM的戴特关于表的规范化曾这样说过:表的行没有顺序。在规范化本身存在问题的情况下,这通常不会被明确指出,但这一点是毋庸置疑的。
科德也这样说过:行(row)不同于记录。记录只有在应用程序进行读取时才有意义。记录是有顺序的,第一个、最后一个、下一个或上一个等顺序都是有意义的。行没有任务物理顺序(ORDER BY是游标中的子句,不属于SQL)。
既然业界的元老们都在思想和策略上反复强调该命题,那么即使不像他们那样执着的数据库工程师和SQL程序员,也将“行没有顺序,也不应该有顺序”的命题内化为法则就不足为奇了。另外,基于集合论严格定义的数据模型能够吸引具有数学素养的工程师,也是自然而然的事情。在这种背景下,为了代替循环,SQL中引入了基于聚合方法的关联子查询。为了实现循环的功能,大家不得不使用关联子查询或自连接。
现代主义改革派的主张
不过,随着时代的发展,SQL也必须适应新的市场需求。在20世纪90年代后半期,甲骨文公司的安迪·维特科夫斯基(Andy Witkowski)等人的团队致力于实现窗口函数的标准化,他们对于引入窗口函数的动机是下面这样描述的。
SQL的一个不足之处是缺乏对分析计算的支持,如移动平均值、累积求和、排名、百分位数、时间方面的提前和滞后等,这些对OLAP应用程序至关重要。窗口函数可作用于有序的数据集。用当前的SQL表达这些函数时需要使用自连接,这并不优雅,而且难以优化。
他们明确宣称:“我们以‘行是有顺序的’为前提。”在关系数据库和SQL出现30年后,他们开始挑战面向集合的SQL法则。
在20世纪90年代后半期,关于窗口函数,甲骨文公司和IBM公司持有相同的想法,他们一起向ANSI提出标准化,“ANSI以前所未有的速度给予了回应”(语出自塞尔科),因此窗口函数定义在了SQL:1999中。但从这一过程来看,关系数据库和SQL的开发社区似乎也对市场需求表现出了非常灵活的应对方式,但对此,并不是所有人都举双手赞成的。维特科夫斯基等人留下了一份关于ANSI标准化讨论过程的论文,其中有这样一段话。
4.对于反对“窗口函数标准化”意见的回答
4.1行聚合不适合传统的SQL模式(mold)
存储过程也不符合传统的SQL模式(SQL本就不是面向过程语言)。所有标准都必须处理市场发展过程中出现的新问题,有时还需要打破常规。如今,sql社区面临OLAP需求增加带来的问题。如果不积极处理该问题,SQL将会背离数据库产业的成长领域,面临过时的危险。
这是一篇充满强烈危机感的文章。在这片文章里,维特科夫斯基等人对全部4条(引入窗口函数的)反对意见进行了反驳,但从最初出现这些反对意见可以推断,还是有保守派提出“使用行顺序的运算违背SQL传统”这种意见。从保守主义的阵营来看,窗口函数在关系数据库和SQL中似乎是一种“犯罪”,它将原本应该被驱逐的物理概念——“顺序”偷偷运了进来。
维特科夫斯基等人认为,即使“畅销”的功能违背传统,数据库供应商等旨在满足市场或客户需求的组织也会积极导入这些功能,而且元老们的影响力在逐渐减小,这也有利于改革。




