乐趣区

关于sql: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 不善于有序计算,无奈用上述天然思路实现,只能用一些乖僻难懂的技巧:把按日期有序的股票记录分成若干组,间断上涨的记录分成同一组,也就是说,某天的股价比上一天是上涨的,则和上一天记录分到同一组,如果上涨了,则开始一个新组。最初看所有分组中最大的成员数量,也就是最多间断上涨的天数。

具体 SQL 如下:

这段 SQL 并不算很长,但嵌套了四层,所用技巧乖僻难懂,个别人很难想出这样的代码。

用 JAVA 实现时,就能够回归自然思路:

前面那段代码就是后面讲述的思路,只有一层循环就能够实现了。

然而,咱们也发现,Java 写出的这段代码,尽管思路简略,难度不大,但显然代码很简短。

这个问题的复杂度并不高,还没波及到常见的分组、连贯等结构化数据计算,否则代码量将更为惊人,限于篇幅,就不再用 JAVA 举例了。

在多样性数据、优化性能、解决大数据等高级性能方面,JAVA 的特点同样是“能实现,但太繁琐”,这里也不再赘述。

JAVA 是个优良的企业级通用语言,但通用的另一层意思往往是不业余,换句话说,JAVA 不足业余的结构化计算类库,代码简短繁琐,算不上现实的 SQL 后计算脚本。

Python pandas

Python 有简捷的语法,还领有泛滥的第三方函数库,其中就有服务于结构化计算的 Pandas。也正因为如此,Pandas 常被用作 SQL 的后计算脚本。

作为结构化计算函数库,Pandas 简化 SQL 简单运算的能力要比 JAVA 强很多。

比方,同样的有序运算“求最长间断上涨天数”,Pandas 代码是这样的:

上述代码中,Pandas 提供了用于结构化计算的数据结构 dataFrame,这种数据结构人造带序号,在有序运算中能够简化代码,比 JAVA 更容易进行跨行取数。此外,Pandas 对 SQL 取数的封装也很紧凑,比 JAVA 代码更加简短。

再比方汇合计算例子:一行拆分为多行。库表 tb 有 2 个字段,其中 ANOMALIES 存储以空格为分隔符的字符串,需将 ANOMALIES 按空格拆分,使每个 ID 字段对应一个成员。

解决前的数据                     

解决后的数据:

Pandas 外围代码如下(省略数据库输入输出,下同):

上述代码中,Pandas 用汇合函数将字符串间接拆分为 dataFrame,再用汇合函数将多个 dataFrame 间接合并,代码十分简练。JAVA 尽管能够实现相似的性能,但都要手工实现,代码要繁琐得多。

作为结构化计算函数库,Pandas 代码确实比 JAVA 简练,但这仅限于复杂度无限的状况下,如果复杂度进一步提高,Pandas 代码也会变得简短难懂。

比方这个波及汇合计算 + 有序计算的例子:间断值班状况。库表 duty 记录着每日值班状况,一个人通常会继续值班几个工作日,之后再换人,当初请依据 duty 顺次计算出每个人间断的值班状况。数据结构示意如下:

解决前(duty)

解决后

外围的 pandas 代码如下:

下面曾经省略了数据库输入输入的过程,能够看到代码还是有点繁琐。

再比方汇合计算 + 多步骤运算的例子:计算分期贷款明细。库表 loan 记录着贷款信息,包含贷款 ID,贷款总额、期数、年利率,示意如下:

须要计算出各期明细,包含:当期还款额、当期利息、当期本金、残余本金。计算结果如下:

实现上述运算的 Pandas 外围代码如下:

能够看到,在简化 SQL 简单运算方面 Python 尽管比 JAVA 强很多,但只限于简略状况,如果需要再简单些,代码也会变得简短难懂。之所以呈现这种景象,可能因为 Pandas 只是第三方函数库,不能失去 Python 从语法层面的底层撑持,设计的专业性也有余。

Pandas 的专业性有余,还体现在多样性数据上。Pandas 没有为各类数据源开发对立接口,只反对常见的本地文件,但不反对简单的数据源,比方 Hadoop、MongoDB,用户还要本人寻找第三方(理论是第四方)函数库,并编写简单的拜访代码。Pandas 甚至没有对立数据库接口,比方 MySQL 就有好几种第三方函数库,常见的有 PyMySQL、sqlalchemy、MySQLdb。不过,这个问题对于大多数桌面利用场景还不重大,常见的数据库 Python 基本上都能简略地反对。

对于多源混合关联问题,只有能读出各种数据源的数据,基本上也就能实现了,Pandas 在这方面的体现根本令人满意。不过,还是下面的说法,对于简略的混合关联关系,Pandas 都容易实现,而一旦呈现较简单的关联运算,实现过程就会变得艰难起来。

在大数据量方面,Pandas 的体现就不尽如人意了。Pandas 没有游标数据类型,这导致解决较大数据量的计算时,必须硬编码实现循环取数,而不能主动进行内外存替换,代码因而异样繁琐。详情可参考《How Python Handles Big Files》

Pandas 的运算性能也个别,但根本够用。令人常常诟病的次要是多线程并行,Python 下很难实现此类运算。比方数据库 IO 个别都较慢,但能够在数据库不忙时应用并行取数的方法来进步取数性能。而 Python 要借助其余第三方函数库能力实现并行,代码异样繁琐,且在表白效率、执行效率、稳定性等不便均不足保障。

Pandas 尽管是结构化计算函数库,但仍不够好用。

esProc

与 Pandas 相似,esProc 也具备丰盛的结构化计算函数,与 Pandas 不同的是,esProc 是由商业公司反对的产品,是业余的结构化计算语言,而不是开源社区的第三方库函数,也不存在一个涣散的下级组织。esProc 能够从全局角度设计统一的结构化计算语法,能够自底向上设计对立的结构化数据类型,使函数之间以最大的灵便度搭配组合,从而快捷不便地解决 SQL 后计算中遇到的问题。

作为业余的结构化计算语言,esProc 善于简化 SQL 简单运算,比方,求最长间断上涨天数,实现后面说过的天然思路,esProc 只需短短 2 行:

上述代码应用了序表和循环函数,序表是专用于结构化计算的数据结构,能够比 Pandas 更容易进行跨行取数,能够更不便地实现有序计算,循环函数能够防止大部分的 for 语句(简单状况下还是应该用 for),能够大幅简化代码。此外,esProc 对 SQL 取数的封装更紧凑,比 Pandas 代码更加简短。

再比方一行拆分为多行,esProc 代码仍然简短:

即便需要复杂度进一步提高,esProc 依然能够轻松实现。

比方间断值班状况,esProc 代码要比 Pandas 简短很多:

再比方计算分期贷款明细,esProc 同样比 Pandas 简短:

对于 Pandas 很难实现的简单运算,esProc 通常也能轻松实现,而且代码不难。比方波及多步骤算法 + 汇合运算 + 动静表构造的工作:将子表横向插入子表。

源表关系

指标后果

esProc 能够大幅简化这段代码:

作为业余的结构化计算语言,esProc 不仅能够大幅简化 SQL 不善于的简单运算,还具备更高级的能力去解决一些非凡状况。

在多样性数据方面,esProc 反对多种文件格式和简单的数据源,比方 Hadoop、MongoDB 等。更进一步,只需应用雷同的代码,数据分析师就能计算起源各异的数据,既包含数据库,也包含非数据库。

在大数据量方面,esProc 从底层提供了游标机制,对下层暗藏了内外存替换细节,容许数据分析师用相似解决小数据量的语法,直观地解决较大的数据量。

比方,库表 orders 记录着电商的大量订单,全副读出会超出内存,当初须要在库外计算每个销售员销售额最大的 3 笔订单。esProc 代码如下:

esProc 也提供了很多简略易用的办法进行性能优化。比方:orders 表每月的数据大抵相等,请按月份进行多线程并行查问,从而大幅提高查问性能。esProc 只需如下代码:

通过后面的比拟咱们能够发现,esProc 具备丰盛的结构化函数,是业余的结构化计算语言,能够大幅简化 SQL 不善于的简单运算逻辑,是更加现实的 SQL 后计算脚本。

退出移动版