Java 搞定 SQL 集合运算的最简方法

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 问题介绍  作为 java 程序员,用代码直接实现类似 SQL 中的交并补差的集合运算,总是要编写大量的代码,如果能有一个专门的外部数据工具,通过写简单类似 SQL 的脚本来实现,在 java 中直接调用并可以返回结果集,就再好不过了。

问题介绍
  作为 java 程序员,用代码直接实现类似 SQL 中的交并补差的集合运算,总是要编写大量的代码,如果能有一个专门的外部数据工具,通过写简单类似 SQL 的脚本来实现,在 java 中直接调用并可以返回结果集,就再好不过了。Java 版集算器正是解决这一难题的神器,通过 SPL 脚本可以直观自然得写出运算,再使用 java 调用 SPL 脚本,使用起来简单,快捷,高效。另外,虽然 SQL 有集合概念,但对于有序集合运算提供的支持却很有限,经常要采用很费解的思路才可以完成, SPL 基于离散数据集模型,能轻松处理有序集合运算。下面我们就由浅入深,举例说明如何使用。

SPL 实现
和集
  示例 1: 求重叠时间段的总天数

MySQL8:

with recursive t(start,end) as (select date'2010-01-07',date'2010-01-9'

union all select date'2010-01-15',date'2010-01-16'
union all select date'2010-01-07',date'2010-01-12'
union all select date'2010-01-08',date'2010-01-11'),

t1(d,end) as (select start,end from t

union all select d+1,end from t1 where d

select count(distinct d) from t1;
  说明:此例先将各时间段转成时间段内所有日子对应的日期,然后再求不同日期的个数

集算器 SPL:
1
 A3: 对 A2 中的每一个时间段构造从 start 到 end 的日期序列
  A4: 求 A3 中所有日期序列的和
  A5: 求 A4 中不重复日期的个数
2
保存脚本文件SumSet.dfx (嵌入 Java 会用到)

差集
  示例 1: 列出英语人口和法语人口均超过 5% 的国家

MySQL8:

with t1(lang) as (select 'English' union all select 'French')

select name from world.country c
where not exists(select * from t1 where lang not in (select language from world.countrylanguage 
    where percentage>=5 and countrycode=c.code
)

);
  说明:此 SQL 只是演示通过双重否定实现差集为空

集算器 SPL:
3
A4: 选出 [“English”,”French”] 与本组语言集合的差为空的组,意思就是选出语言集合包含 English 和 French 的组
4
保存脚本文件DifferenceSet.dfx (嵌入 Java 会用到)

交集
  示例 1: 列出英语人口、法语人口、西班牙语人口分别超过 0.3%、0.2%、0.1% 的国家代码

MySQL8:

with t1 as (select countrycode from world.countrylanguage where language='English' and percentage>0.3),

 t2 as (select countrycode from world.countrylanguage where language='French' and percentage>0.2),
 t3 as (select countrycode from world.countrylanguage where language='Spanish' and percentage>0.1)

select countrycode
from t1 join t2 using(countrycode) join t3 using(countrycode);
  说明:此例只是演示如何求解多个集合的交集

集算器 SPL:
5
A3: 按次序依次查询英语人口超 0.3%、法语人口超 0.2%、西班牙语超 0.1% 的国家代码,并转成序列
  A5: A3 中所有序列交集
6
 保存脚本文件IntersectionSet.dfx (嵌入 Java 会用到)

Java 调用
  SPL 嵌入到 Java 应用程序十分方便,通过 JDBC 调用存储过程方式加载,用和集保存的文件SumSet.dfx,示例调用如下:

...
Connection con = null;
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
//调用存储过程,其中SumSet是dfx的文件名
st =(com. esproc.jdbc.InternalCStatement)con.prepareCall("call SumSet()");
//执行存储过程
st.execute();
//获取结果集
ResultSet rs = st.getResultSet();
...

  替换成DifferenceSet.dfx或IntersectionSet.dfx是同样的道理,只需 call DifferenceSet()或者 call IntersectionSet() 即可。这里只用 Java 片段粗略解释了如何嵌入 SPL,详细步骤请参阅Java 如何调用 SPL 脚本​,也非常简单,不再赘述。同时,SPL 也支持 ODBC 驱动,集成到支持 ODBC 的语言,嵌入过程类似。

扩展节选
  关于集合运算除了上面讲的和差交运算,还可以获取与行号有关的计算,以及有序集合的对位运算。

根据行号取数据
  示例 1: 计算招商银行 (600036) 2017 年第 3 个交易日和倒数第 3 个交易日的交易信息

MySQL8:

with t as (select *, row_number() over(order by tdate) rn from stktrade where sid='600036' and tdate between '2017-01-01' and '2017-12-31')

select tdate,open,close,volume from t where rn=3

union all

select tdate,open,close,volume from t where rn=(select max(rn)-2 from t);

集算器 SPL:
7
 示例 2: 计算招商银行 (600036) 最近 20 个交易日的平均收盘价

MySQL8:

with t as (select *, row_number() over(order by tdate desc) rn from stktrade where sid='600036')
select avg(close) avg20 from t where rn<=20;
集算器 SPL:
8
求满足条件的记录的行号
  示例 1: 计算招商银行 (600036)2017 年经过多少交易日收盘价达到 25 元

MySQL8:

with t as (select *, row_number() over(order by tdate) rn from stktrade where sid='600036' and tdate between '2017-01-01' and '2017-12-31')
select min(rn) from t where close>=25;
集算器 SPL:
9
 示例 2: 计算格力电器 (000651) 2017 年涨幅 (考虑停牌)

MySQL8:

with t as (select * from stktrade where sid='000651'),

 t1(d) as (select max(tdate) from t where tdate<'2017-01-01'),
 t2(d) as (select max(tdate) from t where tdate<'2018-01-01')

select s2.close/s1.close-1 rise
from (select * from t,t1 where tdate=d) s1,

 (select * from t,t2 where tdate=d) s2;

集算器 SPL:
10
 A2: 数据按交易日从小到大排序
  A3: 从后往前查找交易日在 2017-01-01 之前的最后一条记录在序列中的行号
  A4: 求 2016 年收盘价
  A5: 求 2017 年收盘价,其中 A2.m(-1) 取倒数第 1 条记录,即 2017 年最后一个交易日对应的记录
11
 示例 3: 列出 2017 年信息发展 (300469) 交易量超过 250 万股时的交易信息及各日涨幅(考虑停牌)

MySQL8:

with t as (select *, row_number() over(order by tdate) rn

from stktrade where sid='300469' and tdate<=date '2017-12-31'),

t1 as (select * from t where tdate>=date'2017-01-01' and volume>=2500000)

select t1.tdate, t1.close, t.volume, t1.close/t.close-1 rise
from t1 join t on t1.rn=t.rn+1;

集算器 SPL:
12
求最大值或最小值所在记录的行号
  示例 1: 计算招商银行 (600036) 2017 年最早的最低价与最早的最高价间隔多少交易日

MySQL8:

with t as (select *, row_number() over(order by tdate) rn from stktrade where sid='600036' and tdate between '2017-01-01' and '2017-12-31'),

 t1 as (select * from t where close=(select min(close) from t)),
 t2 as (select * from t where close=(select max(close) from t))

select abs(cast(min(t1.rn) as signed)-cast(min(t2.rn) as signed)) inteval
from t1,t2;
集算器 SPL:
13
示例 2: 计算招商银行 (600036) 2017 年最后的最低价与最后的最高价间隔多少交易日

MySQL8:

with t as (select *, row_number() over(order by tdate) rn from stktrade where sid='600036' and tdate between '2017-01-01' and '2017-12-31'),

 t1 as (select * from t where close=(select min(close) from t)),
 t2 as (select * from t where close=(select max(close) from t))

select abs(cast(max(t1.rn) as signed)-cast(max(t2.rn) as signed)) inteval
from t1,t2;
集算器 SPL:
14
有序集合间的对位计算
  示例 1: 求 2018 年 3 月 6 日到 8 日创业板指 (399006) 对深证成指 (399001) 的每日相对收益率

MySQL8:

with t1 as (select *,close/lag(close) over(order by tdate) rise from stktrade where sid='399006' and tdate between '2018-03-05' and '2018-03-08'),

 t2 as (select *, close/lag(close) over(order by tdate) rise from stktrade where sid='399001' and tdate between '2018-03-05' and '2018-03-08')

select t1.rise-t2.rise
from t1 join t2 using(tdate)
where t1.rise is not null;
集算器 SPL:
15
SPL 优势
有库写 SQL,没库写 SPL
  用 Java 程序直接汇总计算数据,还是比较累的,代码很长,并且不可复用,很多情况数据也不在数据库里,有了 SPL,就能像在 Java 中用 SQL 一样了,十分方便。

常用无忧,不花钱就能取得终身使用权的入门版
  如果要分析的数据是一次性或临时性的,润乾集算器每个月都提供免费试用授权,可以循环免费使用。但要和 Java 应用程序集成起来部署到服务器上长期使用,定期更换试用授权还是比较麻烦,润乾提供了有终身使用权的入门版,解决了这个后顾之忧,获得方式参考 如何免费使用润乾集算器?

技术文档和社区支持
  官方提供的集算器技术文档本身就有很多现成的例子,常规问题从文档里都能找到解决方法。如果获得了入门版,不仅能够使用 SPL 的常规功能,碰到任何问题都可以去乾学院上去咨询,官方通过该社区对入门版用户提供免费的技术支持。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
11天前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
21 2
|
11天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
15天前
|
存储 Java
判断一个元素是否在 Java 中的 Set 集合中
【10月更文挑战第30天】使用`contains()`方法可以方便快捷地判断一个元素是否在Java中的`Set`集合中,但对于自定义对象,需要注意重写`equals()`方法以确保正确的判断结果,同时根据具体的性能需求选择合适的`Set`实现类。
|
15天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
55 4
|
15天前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
15天前
|
Java 开发者
|
19天前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
44 2
|
20天前
|
SQL BI 数据库
SQL操作的一些基本方法
【10月更文挑战第27天】SQL操作的一些基本方法
31 3
|
20天前
|
SQL 监控 固态存储
SQL优化有哪些方法?
【10月更文挑战第27天】SQL优化有哪些方法?
15 3
|
15天前
|
存储 Java 开发者
Java中的集合框架深入解析
【10月更文挑战第32天】本文旨在为读者揭开Java集合框架的神秘面纱,通过深入浅出的方式介绍其内部结构与运作机制。我们将从集合框架的设计哲学出发,探讨其如何影响我们的编程实践,并配以代码示例,展示如何在真实场景中应用这些知识。无论你是Java新手还是资深开发者,这篇文章都将为你提供新的视角和实用技巧。
12 0
下一篇
无影云桌面