浅解比 SQL 更好用的 SPL(二)

简介: 从 SQL 到SPL基本查询语法迁移 之多表操作 上一篇我们针对单表的情形了解了如何把数据计算从 SQL 查询迁移到集算器,或者更准确地说,迁移到集算器所使用的SPL集算语言。这个迁移过程,既有相同的概念,也有不同的思路。

从 SQL 到SPL基本查询语法迁移 之多表操作

上一篇我们针对单表的情形了解了如何把数据计算从 SQL 查询迁移到集算器,或者更准确地说,迁移到集算器所使用的SPL集算语言。这个迁移过程,既有相同的概念,也有不同的思路。

接下来,我们一起针对多表的情况看一下集算器和SPL语言是如何发挥更大的优势的。

JOIN 连接两个记录
在前面的例子中,我们得到了每个雇员的销售额,如果进一步还想知道每个雇员给出的最小折扣,那就又复杂了些。因为折扣信息在另一张订单明细表里。急性子的朋友可能上来就要 JOIN 两个表,然后再聚合两个测度字段——这样就算错了!正确的做法应该是每个测度字段先按分组聚合出结果,之后再 JOIN。这是因为先 JOIN 的话可能导致结果中出现重复记录。

按照这个思路写出 SQL,并和集算器中的SPL代码进行比较:
SQL
select t1.employeeId, salesAmount, lowestDiscount from (
select employeeId, sum(money) salesAmount from order
where orderDate>=’2012-01-01′ and orderDate<‘2012-02-01’
group by employeeId
having sum(money)>5000) t1
left join (
select employeeId, min(discount) lowestDiscount from order
join orderDetail on order.orderId=orderDetail.orderId
where orderDate>=’2012-01-01′ and orderDate<‘2012-02-01’
group by employeeId) t2
on t1.employeeId=t2.employeeId
1
A5 之前是我们做过的聚合符合条件的按雇员分组的销售额;
A6 查出订单明细表的所有数据;

A7 中的SPL用到了对应 SQL 的多表连接的新函数 join。join 函数把两个表连接起来,这里它的参数的含义是:将 A3 序表起一个别名 order,A6 序表起一个别名 orderDetail,然后用两个表各自的 orderId 作为关联字段,观察 A7 的结果如下:
2

可以看到,join 后形成的序表有 order、orderDetail 两个字段,两个字段的值分别直接指向了两个原始序表的记录,这就是说字段的值可以是复杂数据类型(包括序表、序列类型),也可以嵌套多层结构的数据,这是 SQL 语法里不允许的,也是SPL的特色和优势之一。

下图比较形象地说明了这种结构(长方形表示序表、椭圆形表示记录、三角形表示关联字段):
3

A8 直接用SPL中的 group 函数对这个复杂结构的序表进行分组聚合运算,获得各个雇员曾经给出的最小折扣。

再需要注意的一点是 A3 序表被后面两个不同的动作(A4、A7)都使用了一次,达到了中间结果复用的效果。这种方式对于越是复杂的计算,往往作用越大,可以起到类似“数据模块化”的作用。

在 A9 中通过SPL的 join 函数把 A5(销售额超过 5000)、A8(最小折扣)两个序表连接起来;

最后,A10 使用 new 函数生成新的序表结构,而数据来自 A9 复杂结构记录的不同层次位置。

A10 最终的结果如下:
4

简单回顾一下,对于最后这个比较复杂的 SQL,如果你是个 SQL 高手,可能会看出第二个子查询里的 where 并不是必须的,之所以保留它,是因为有可能会缩小处理数据的范围,从而提升一些性能。这也是 SQL 的另一个特点,一方面需要不喘气的一句话把整个查询表达出来,另一方面还需要同时考虑性能优化因素,甚至即便考虑到了优化方案,也不一定能轻松、自然地描述出来。

在上面的例子中,不难体会出集算器以及SPL对分步过程的重视,每一个步骤的结果都是可以随时观察的,而且前面步骤的结果也可以重复利用,同时执行步骤也可以被程序员自由定制。这些特点最直接的好处是降低了学习和编码的难度,而更本质的是符合人的自然思维,为描述复杂计算奠定了基础。

UNION 等合并两个集合
SQL 中还有一类针对多个集合(表)的运算,就是常说的并、合、交、差(UNION、UNION ALL、INTERSECTION、MINUS),与之对应的,在SPL中表示为 &、|、^、。

集合运算时常需要判断一条记录是否重复,在这个细节上,SQL 和SPL有一点区别。SPL里因为序表、记录,以及字段的值都被看成是一个对象,所以在进行并集运算时,可以比对元素是否为同一个对象,而 SQL 的记录是抽象的,不是一个实体对象,所以只能通过逐个比对两条记录的字段值来判断是否重复。

我们来看一下实际的例子:
5
A3 序表的结果:
6

B3 序表的结果:
7

A3&B3,去掉重复合并到一起,并集运算后得到 A4 序表的结果:
8

A3|B3,保留重复合并到一起,合集运算后得到 B4 序表的结果:
9

A3^B3,取 A3 和 B3 里相同的记录,交集运算后得到 A5 序表的结果:
10

A3B3,A3 里去掉 B3 中存在的记录,差集运算后得到 A5 序表的结果:
12

其它常用语法
最后,再看两个常用的 SQL 函数语法,我们来对比看一下SPL的实现。

CASE WHEN …
SQL 中的 case when … then … else … end,在SPL中用 if 函数,语法是if(条件, 真值, 假值),下面的例子是把 employeeId<5 的分为一组,剩余的分到另一组:
13
COALESCE(exp1,exp2…expn)
SPL中仍然用 if 函数,if(条件, 真值, 假值),下面这个例子把 1000 这个特殊的值赋值给为 null 的 employeeId。
14
集算器(SPL)≠SQL
看完上面这些例子,会给人一个感觉:集算器,或者其中的SPL代码只是 SQL 的替代品,而常用的关系数据库系统(RDBMS)本身已经是存储能力(数据表)+ 计算能力 (SQL) 的综合体了,还要这么一个外来的计算体系干嘛?

针对这个疑问,有两个层面的答案。首先是数据层面,并非所有要计算的数据都在数据库里。当你手边有个文本、excel 或从一个网络服务临时得到一些数据想要计算,或者从大量终端采集上来的数据马上要处理出结果……如果这些都不得不倒腾到数据库里然后再计算,还真是有点太绕了,更何况还可能涉及到数据库的安装部署,或者权限控制等琐碎而现实的问题。

其次是计算层面,对于很多复杂的计算过程,SQL 因为天生缺陷无法做到开发高效、维护高效、执行效高。这也是我们这篇文章最想说明的地方,SQL 的计算主要还是面向查询,而这些对“高效”的追求,面向的是更广泛的数据计算,这正是集算器和SPL语言所要重点改善的。

正因为有了这两个层面的原因,集算器和SPL语言已经可以独立于各种数据存储形式,在“存储”和“应用”之间,作为一个功能完整、形式灵活、部署方便的“数据计算中间件”而存在。这方面的内容,我们会在后面的章节做更多的介绍和探讨。

这里,我们只是先简单看一下集算器和SPL语言如何基于文本、Excel 等数据源进行计算。事实上,前面这些例子中的计算步骤完全不用改写,只需要改变加载数据那一句就可以了。也就是把:

=A1.query(“select * from order”)

改为下列任意方式之一:

=file(“d:/data/order.txt”).import@t()// 从文本文件加载数据表

=file(“d:/data/orderDetail.xls”).importxls@t()// 从 excel 加载数据表

=httpfile(“ http:/ /127.0.0.1/service ”,” param1=value1&param2=value2″) // 从 http server 加载数据表

……

很明显,通过这种简单明了的数据加载方式,可以将各种数据源的数据形成统一的“序表”,从而在一个计算过程里可以轻松混合使用。换句话说,不必为了计算能力而要求必须统一存储方式。同样的,在集算器和SPL的环境中,计算结果的存储,也和加载数据一样方便,也是多样化的,可以由程序员自由选择。

相关文章
|
5月前
|
SQL 数据采集 JSON
弱结构化日志 Flink SQL 怎么写?SLS SPL 来帮忙
弱结构化日志 Flink SQL 怎么写?SLS SPL 来帮忙
125499 137
|
SQL 存储 Java
Java 结构化数据处理开源库SPL,再也不用苦哈哈写SQL了
现代Java应用架构越来越强调数据存储和处理分离,以获得更好的可维护性、可扩展性以及可移植性,比如火热的微服务就是一种典型。
175 0
|
SQL 存储 消息中间件
SPL比SQL更难了还是更容易了?
SPL作为专门用于结构化和半结构化数据的处理技术,在实际应用时经常能比SQL快几倍到几百倍,同时代码还会短很多,尤其在处理复杂计算时优势非常明显。用户在看到这些应用效果后对SPL往往很感兴趣
|
10天前
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
3月前
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
69 13
|
3月前
|
SQL
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。
|
3月前
|
SQL 存储 网络安全
关系数据库SQLserver 安装 SQL Server
【7月更文挑战第26天】
48 6
|
2月前
|
SQL 安全 Java
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
241 0
|
3月前
|
存储 SQL C++
对比 SQL Server中的VARCHAR(max) 与VARCHAR(n) 数据类型
【7月更文挑战7天】SQL Server 中的 VARCHAR(max) vs VARCHAR(n): - VARCHAR(n) 存储最多 n 个字符(1-8000),适合短文本。 - VARCHAR(max) 可存储约 21 亿个字符,适合大量文本。 - VARCHAR(n) 在处理小数据时性能更好,空间固定。 - VARCHAR(max) 对于大文本更合适,但可能影响性能。 - 选择取决于数据长度预期和业务需求。
155 1
|
3月前
|
SQL Oracle 关系型数据库
MySQL、SQL Server和Oracle数据库安装部署教程
数据库的安装部署教程因不同的数据库管理系统(DBMS)而异,以下将以MySQL、SQL Server和Oracle为例,分别概述其安装部署的基本步骤。请注意,由于软件版本和操作系统的不同,具体步骤可能会有所变化。
172 3
下一篇
无影云桌面