【摘要】
SQL 虽然有集合概念,但对于集合运算、特别是有序集合运算,提供的支持却很有限,经常要采用很费解的思路才能完成,计算效率也不佳。而集算器 SPL 在方面则要直观许多,可以按自然思维习惯写出运算。这里对 SQL 和集算器 SPL 在集合运算和行号相关运算方面进行了对比,如果需要了解更多,请前往乾学院:SQL 难点解决:集合及行号!

1、  和集

示例 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:

 

A

1

=connect("mysql")

2

=A1.query@x("select   date'2010-01-07'start,date'2010-01-9'end 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'")

3

=A2.(periods(start,end))

4

=A3.conj()

5

=A4.icount()

A3: 对 A2 中的每一个时间段构造从 start 到 end 的日期序列

A4: 求 A3 中所有日期序列的和

A5: 求 A4 中不重复日期的个数

2、  差集

示例 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:

 

A

1

=connect("mysql")

2

=A1.query("select   CountryCode,Name,Language,Percentage from world.countrylanguage cl join   world.country c on cl.countrycode=c.code where percentage>5")

3

=A2.group(CountryCode)

4

=A3.select(["English","French"]\~.(Language)==[])

5

=A4.new(~.Name:name)

A4: 选出[“English”,”French”]与本组语言集合的差为空的组,意思就是选出语言集合包含English和French的组

3、  交集

示例 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:

 

A

1

=connect("mysql")

2

[English,French,Spanish]

3

[0.3,0.2,0.1]

4

=A2.(A1.query@i("select   countrycode from world.countrylanguage where language=? and   percentage>?",~,A3(#)))

5

>A1.close()

6

=A4.isect()

A3: 按次序依次查询英语人口超0.3%、法语人口超0.2%、西班牙语超0.1%的国家代码,并转成序列

A5: A3中所有序列交集

4、  根据行号取数据

示例 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:

 

A

1

=connect("mysql")

2

=A1.query@x("select   * from stktrade where sid='600036'and tdate between'2017-01-01'and  '2017-12-31'order by tdate")

3

=A2(3)|A2.m(-3)

A3: 第 3 条记录和倒数第 3 条记录的和集

示例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:

 

A

1

=connect("mysql")

2

=A1.query@x("select   * from stktrade where sid='600036'order by tdate")

3

=A2.m(-20:)

4

=A3.avg(close)

A2: 将600036的交易记录按日期排序

A3: 取从倒数20条到末尾的所有记录

A4: 求A3中所有记录收盘价的平均值

5、  求满足条件的记录的行号

示例 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:

 

A

1

=connect("mysql")

2

=A1.query@x("select   * from stktrade where sid='600036'and tdate between'2017-01-01'and  '2017-12-31'order by tdate")

3

=A2.pselect(close>=25)

A3: 从前往后查找第 1 个收盘价达到 25 元的记录位置

示例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:

 

A

1

=connect("mysql")

2

=A1.query@x("select   * from stktrade where sid='000651'and tdate<'2018-01-01'order by tdate  ")

3

=A2.pselect@z(tdate < date("2017-01-01"))

4

=A2(A3).close

5

=A2.m(-1).close

6

=A5/A4-1

A2: 数据按交易日从小到大排序

A3: 从后往前查找交易日在2017-01-01之前的最后一条记录在序列中的行号

A4: 求2016年收盘价

A5: 求2017年收盘价,其中A2.m(-1)取倒数第1条记录,即2017年最后一个交易日对应的记录

示例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:

 

A

1

=connect("mysql")

2

=A1.query@x("select   * from stktrade where sid='300469'and tdate<= date'2017-12-31'order by   tdate")

3

=A2.pselect@a(tdate>=date("2017-01-01")   && volume>2500000)

4

=A3.new(A2(~).tdate:tdate,   A2(~).close:close, A2(~).volume:volume, A2(~).close/A2(~-1).close-1:rise)

A3: 求出2017年交易量超250万股所有记录的行号

A4: 根据行号计算相应的日期、收盘价、交易量、涨幅

6、  求最大值或最小值所在记录的行号

示例 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:

 

A

1

=connect("mysql")

2

=A1.query@x("select   * from stktrade where sid='600036'and tdate between'2017-01-01'and  '2017-12-31'order by tdate")

3

=A2.pmax(close)

4

=A2.pmin(close)

5

=abs(A3-A4)

A3: 从前往后找最大收盘价在序列中的行号

A4: 从前往后找最小收盘价在序列中的行号

示例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:

 

A

1

=connect("mysql")

2

=A1.query@x("select   * from stktrade where sid='600036'and tdate between'2017-01-01'and  '2017-12-31'order by tdate")

3

=A2.pmax@z(close)

4

=A2.pmin@z(close)

5

=abs(A3-A4)

A3: 从后往前找最大收盘价在序列中的行号

A4: 从后往前找最小收盘价在序列中的行号

7、  有序集合间的对位计算

示例 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:

 

A

1

=connect("mysql")

2

=["399006","399001"].(A1.query("select   * from stktrade where sid=? and tdate between'2018-03-05'and  '2018-03-08'",~))

3

>A1.close()

4

=A2.(~.calc(to(2,4),close/close[-1]))

5

=A4(1)--A4(2)

A2: 依次查询399006和399001从2018年3月5日到8日的交易数据

A4: 依次计算A2中2个序表从第2条记录到第4条记录的涨幅,也就是399006和399001从2018年3月6日到8日的每天涨幅

A5: 对位相减,即可算出每日相对收益率

SQL 难点解决:集合及行号相关推荐

  1. SQL 难点解决:循环计算

    SQL 虽然可以对集合中的记录进行循环计算, 但在循环计算过程中利用中间变量.同时计算多个值.前后记录访问.减少循环次数等方面差强人意.而集算器 SPL 则要直观许多,可以按自然思维习惯写出运算.这里 ...

  2. SQL Server之 (四) ADO增删查改 登录demo 带参数的sql语句 插入自动返回行号

    SQL Server之 (四) ADO增删查改  登录demo  带参数的sql语句  插入自动返回行号 自己学习笔记,转载请注明出处,谢谢!---酸菜 1.什么是ADO.NET ADO.NET是一组 ...

  3. oracle改字体大小_集成开发环境PL/SQL Developer教程:设置行号和修改字体大小

    PL/SQL Developer是一个集成开发环境,它专门针对Oracle数据库的存储程序单元的开发所用.PL/SQL开发者在开发Oracle应用程序的时候注重于开发工具简单易用,代码简洁和开发效率高 ...

  4. oracle 检索行号,sql使用row_number()查询标记行号

    背景: 在分页功能中,记录需分页显示,需要row_number()函数标记行号. 数据表: 排序之前数据表显示: sql语句: 1 select ROW_NUMBER() over(order by ...

  5. sql查询排行获取列表行号

    mysql 中关于获取行号@rownum:=@rownum+1 mysql中没有获取行号的函数,因此需要通过一些自定义语句来进行获取.通常做法是,通过定义用户变量@rownum来保存表中的数据.通过赋 ...

  6. SQL Server 查询时显示行号

    上图,因为自增列(b_Id)会断开,在做分页的时候不方便.可以人为地加一列行号,如下代码: SELECT * ,ROW_NUMBER() OVER ( ORDER BY b_time ) AS 行号 ...

  7. SQL 难点解决:直观分组

    1.    对位分组 示例 1:按顺序分别列出使用 Chinese.English.French 作为官方语言的国家数量 MySQL8: with t(name,ord) as (select 'Ch ...

  8. 谈下这几天sybase数据库获取行号遇到的坑

    关于Sybase数据库获取行号的问题 这几天在搞一个sybase数据库的问题(此前连听都没听说过的数据库,是我才疏学浅了),目的是获取到数据库的行号,前辈的源代码是这样的: INSERT INTO [ ...

  9. mysql 分组行号_mysql 显示行号,以及分组排序

    建表: CREATE TABLE `my_tb` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parent_code` varchar(255) DEFAULT ...

最新文章

  1. 三插头内部结构图_10寸三防加固平板电脑 条码数据采集器 工业级耐摔防爆 高清屏幕带网口串口 支持航空插头...
  2. 按覆盖地理范围的不同计算机网络可分为,按网络覆盖的地理范围进行分类,计算机网络可以分为:...
  3. 查询选修c语言课程的学生学号和姓名,数据库实验(学生信息表)
  4. Bug整理——$(window).height()获取到$(document).height()的问题
  5. 成功解决Lib\sre_compile.py, line 17, in module assert _sre.MAGICMAGIC SRE module mismatch
  6. oracle 列级外键,Oracle 中的外键与锁
  7. UVa 12657 - Boxes in a Line ( 双向链表 )
  8. c语言课后答案谢延红,C语言程序设计基础第4,5章 课后习题答案
  9. Ubuntu Linux 环境变量PATH设置
  10. 嵌入式开发 ARM Cortex-M3处理器技术优势分析
  11. 《又到毕业季》MATLAB GUI 鼠标键盘交互
  12. CNCC 2022| 隐私计算:理论、技术、应用与未来
  13. 如何使用命令提示符轻松地将GPT转换为MBR而不会丢失数据?
  14. 【速成MSP430f149】电赛期间学习MSP430f149笔记
  15. Cosine Similarity 与 L2distanse
  16. 如何在SuperMap iDesktop制作卫星地图
  17. PS---星空名片制作教程
  18. Java删除表格的基本代码,Java 删除 Excel 中的空白行和列
  19. Android开发 - PsyDuck说明书
  20. 面对困难,你可以等死,也可以马上动手解决问题,解决完一个,就再解决一个,然后就可以回家了。...

热门文章

  1. 华为Mate30EPro和华为Mate30的区别
  2. 真实评测:华为mate30epro和mate30的区别-哪个好
  3. 信息技术兴趣小组总结
  4. VMware16-安装Windows11体验,解决“TPM“可信任平台模块问题
  5. Google收录了内页,但是百度不收录新站内页
  6. android 彩信 下载流程,android短彩信收发流程(应用层).pdf
  7. SDHC(高容量SD存储卡)
  8. python+requests+pytest 接口自动化框架(八)
  9. HTK standard lattice format
  10. 大数据处理技术之冗余消除