SQL 的后计算脚本


【摘要】
SQL 的后计算脚本用于实现 SQL 不适合的某些复杂运算 , 本文从此类工具中精心挑选了三种 , 从开发效率、语法表达能力、结构化函数库等方面进行深度对比 , 考察了各脚本在集合计算、有序计算等重点运算上的表现 , esProc 在这几款工具中的表现最为出色 。 点击SQL 的后计算脚本了解详情 。
大多数情况下 , 我们用 SQL(存储过程)就可以完成数据库计算 , 但如果遇到 SQL 不擅长的某些复杂运算 , 就只能用其他程序语言把数据读出库外 , 然后在数据库外完成计算 , 这样的程序语言经常是以简单脚本的形式出现 , 我们在这里称为 SQL 的后计算脚本 。
SQL 不擅长的运算主要包括复杂的集合计算、有序计算、关联计算、多步骤计算等 。 SQL 集合化不够彻底 , 没有显式的集合数据类型 , 导致计算过程中产生的集合难以复用 , 比如分组后必须强制汇总 , 而基于分组后的子集无法再计算;SQL 基于无序集合理论设计 , 处理跨行组及排名等有序运算非常麻烦 , 经常用 JOIN 或子查询临时生成序号 , 不仅难写而且运算效率很低 。 SQL 还不支持记录的引用 , 只能用子查询或 JOIN 语句描述关联关系 , 一旦遇到层级较多或自关联的情况 , 代码就会异常复杂;SQL 本身也不提倡多步骤代码 , 经常迫使程序员写出嵌套很多层的长语句 , 虽然用存储过程可以一定程度解决这个问题 , 但有时实际环境不允许我们使用存储过程 , 比如 DBA 严格控制存储过程的权限、旧数据库和小型数据库不支持存储过程等 , 而且存储过程的调试也很不方便 , 并不是很适合写出有过程的计算 。
除了上述复杂运算 , 还有一些情况也会用到 SQL 的后计算脚本 。 比如 , 计算逻辑需要在不同种类的数据库间迁移 , 涉及到非关系数据库;输入源或输出目标不止数据库 , 而是 Excel、文本等文件;还可能在多个数据库之间进行混合计算 。 这些都会涉及库外计算 , 用到 SQL 的后计算脚本 。
对 SQL 的后计算脚本而言 , 最重要的功能当然还是实现 SQL 不擅长的那些复杂运算 。 除此之外 , 最好还能具备一些更高级的特性 , 比如计算文件、非关系数据库等多样性数据、能处理较大的数据量、运算性能 不能太慢等 。 当然 , 最基本的是要方便地支持读写数据库 , 这样才能实现 SQL 的后计算 。
常见的用于 SQL 后计算脚本有 JAVA、Python pandas、esProc , 下面就让我们深入了解这些脚本 , 看看它们进行 SQL 后计算时的能力差异 。
JAVA
C++、JAVA 等高级语言理论上无所不能 , 自然也能实现 SQL 不擅长的运算 。 JAVA 支持泛型 , 集合化比较彻底 , 可以实现复杂的集合运算 。 JAVA 的数组本来就有序号 , 可以实现有序运算 。 JAVA 支持对象引用 , 可用引用来表示关系 , 关联运算也没什么问题 。 JAVA 支持分支、循环等过程性语法 , 可轻松实现多步骤复杂运算 。
但是 , JAVA 缺乏结构化类库 , 连最简单的结构化计算都必须硬编码实现 , 最基本的结构化数据类型也要手工建立 , 这会导致代码冗长繁琐 。
举个有序计算的例子:求某支股票最长连续上涨天数 。 库表 AAPL 存储某支股票的股价信息 , 主要字段有交易日期、收盘价 , 请计算该股票最长的连续上涨天数 。
按自然思路实现这个任务:对日期有序的股票记录进行循环 , 如果本条记录与上一条记录相比是上涨的 , 则将连续上涨天数(初始为 0)加 1 , 如果是下跌的 , 则将连续上涨天数和当前最大连续上涨天数(初始为 0)相比 , 选出新的当前最大连续上涨天数 , 再将连续上涨天数清 0 。 如此循环直到结束 , 当前最大连续上涨天数即最终的最大连续上涨天数 。
SQL 不擅长有序计算 , 无法用上述自然思路实现 , 只能用一些古怪难懂的技巧:把按日期有序的股票记录分成若干组 , 连续上涨的记录分成同一组 , 也就是说 , 某天的股价比上一天是上涨的 , 则和上一天记录分到同一组 , 如果下跌了 , 则开始一个新组 。 最后看所有分组中最大的成员数量 , 也就是最多连续上涨的天数 。