SQL 难点解决:循环计算
SQL 虽然可以对集合中的记录进行循环计算, 但在循环计算过程中利用中间变量、同时计算多个值、前后记录访问、减少循环次数等方面差强人意。而集算器 SPL 则要直观许多,可以按自然思维习惯写出运算。这里对 SQL 和集算器 SPL 在循环计算方面进行了对比。
1、 求 20 以内的质数
MySQL8:
with recursive t(n) as (
select 1
union all select n+1 from t where n<20)
select n from t
where n!=1 and n not in (select t1.n*t2.n from t t1 join t t2 on t1.n<=t2.n where t1.n>1 and t2.n between 2 and 20/2 and t1.n*t2.n<=20);
集算器SPL:
A | |
1 | =to(20) |
2 | =to(2,20/2) |
3 | =A2.(A1.step(~,~*2)) |
4 | =A1.to(2,)\A3.conj() |
A3: 针对A2中每一个成员,求出它在20以内的n倍数(n>1),并将所有计算结果组成序列返回
A4: 除去1和所有20以内的合数即为20以内的素数,其中A3.conj()求出20以内的合数
2、 求格力电器 (000651) 最长上涨天数
MySQL8:
with recursive t1 as (select *,row_number() over(order by tdate) rn from stktrade where sid='000651'),
t2 as (select *,0 rise from t1 where rn=1
union all
select t1.*, if(t1.close>t2.close,t2.rise+1,0) from t1 join t2 on t1.rn=t2.rn+1)
select max(rise) from t2;
集算器SPL:
A | |
1 | =connect("mysql") |
2 | =A1.query@x("select * from stktrade where sid='000651'order by tdate") |
3 | =a=0,A2.max(a=if(close>close[-1],a+1,0)) |
A2: 按交易日期升序排序
A3: 循环计算 a,若收盘价比上一交易日收盘价高则加 1,否则重新置为 0,然后求每条记录算出来的 a 的最大值
3、 求信息发展 (300469)2018 年 2 月 14 日距历史最高收盘价跌幅
MySQL8:
select 1-t2.close/t1.close fall
from (select max(close) close from stktrade where sid='300469') t1,
(select close from stktrade where sid='300469' and tdate='2018-02-14') t2;
集算器SPL:
A | |
1 | =connect("mysql") |
2 | =A1.query@x("select * from stktrade where sid='300469'order by tdate") |
3 | =A2.top@1(1,(if(tdate==date("2018-02-14"),A4=close),-close)) |
4 | =1+@/A3 |
A3: 在循环计算A2中-close最小值(即close最大值)的过程中,将2018年2月14日收盘价close设到A4
A5: @表示本格格值
4、 求信息发展 (300469)2018 年 1 月 1 日到 10 日每天累积成交量
MySQL8:
select tdate,volume,sum(volume) over(order by tdate) cum
from stktrade
where sid='300469' and tdate between '2018-01-01' and '2018-01-10';
集算器SPL:
A | |
1 | =connect("mysql") |
2 | =A1.query@x("select tdate,volume,0 cum from stktrade where sid='300469'and tdate between '2018-01-01'and'2018-01-10'order by tdate") |
3 | =A2.run(cum=cum[-1]+volume) |
A3: 针对A2中每条记录,将volume列重新赋值为上条记录的cum列和本条记录的volume列之和,最后返回A2
5、 从 2018 年 1 月 1 日起信息发展 (300469) 经过多少交易日总成交量达到 1000000 股
MySQL8:
with t as (select row_number() over(order by tdate) rn,
sum(volume) over(order by tdate) cum
from stktrade
where sid='300469' and tdate>='2018-01-01')
select min(rn) from t where cum>=1000000;
集算器SPL:
A | |
1 | =connect("mysql") |
2 | =A1.query@x("select tdate,volume from stktrade where sid='300469'and tdate>='2018-01-01' order by tdate") |
3 | =A2.iterate((@+=volume,~~+1),0,@>1000000) |
A3: A.iterate(x,a,c)相当于变量~~初始赋值为a,然后对A中成员循环,每次将x的计算结果赋给~~,再判断c是否为真,若真则继续循环,否则返回~~。@表示本格格值,在此用作中间变量。
6、 重叠部分不重复计数时求多个时间段包含的总天数
MySQL8:
with tt(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'),
t as (select * from tt order by start),
tmp as (
select t.start, t.end, @m:=if(@m>@p,@m,@p) m,@p:=end,
case when @m>end then 0 when @m<start then datediff(end,start)+1 else datediff(end,@m) end days
from t,(select @m:=date'1970-01-01',@p:=@m) s
)
select sum(days) from tmp;
说明:@m为本记录以前的结束日期最大值,@p为本记录结束日期, days为本记录自以前最大结束日期后经过的天数。此问题的其它解决方法可参考《SQL 难点解决:集合及行号》和《SQL 难点解决:记录的引用》中相同示例。
集算器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.sort(start) |
4 | =A3.iterate((@=max(@, end[-1]), ~~ + if(@>=end:0, @<start:end-start+1, end-@)), 0) |
A4: A.iterate函数无第3个参数表示循环A中所有成员
7、 列出信息发展 (300469) 和招商银行 (600036) 从 2018 年 6 月 11 日到 15 日的交易信息及累积换手率
MySQL8:
with k as (select sid,circulation,tdate start,lead(tdate,1, date_add(now(),interval 1 day))over(partition by sid order by tdate) end
from stocks)
select t.*, k.circulation circ, sum(t.volume/k.circulation/10000) over(partition by sid order by tdate) rate
from stktrade t join k on t.sid=k.sid and t.tdate>=k.start and t.tdate<k.end
where t.sid in ('300469','600036') and t.tdate between '2018-06-11' and '2018-06-15';
集算器SPL:
A | |
1 | =connect("mysql") |
2 | =A1.query("select * from stocks where sid in ('600036','300469') order by sid,tdate") |
3 | =A1.query@x("select * from stktrade where sid in ('600036','300469') and tdate between '2018-06-11'and'2018-06-15'order by sid,tdate") |
4 | =A3.derive((p=A2.pselect@bs(sid:A3.sid,tdate:A3.tdate), p=if(p<0,-p-1,p), A2(p).circulation):circ, iterate(~~+volume/circ/10000,0;sid):rate) |
AA2: 流通股本信息按股票代码和日期排序
A3: 交易信息按股票代码和日期排序
A4: 先用A2.pselect@bs(sid:A3.sid,tdate:A3.tdate)查找对应日期的流通股本,若找到则返回行号,否则返回-插入位置,然后用p=if(p<0,-p-1,p)计算出当前交易日对应的流通股本在A2中行号,最后取出流通股本并赋值给circ列;在循环函数中,iterate(x,a;G)在初始或G发生变化时将a赋值给变量~~,然后将x的计算结果赋给~~。
8、 列出招商银行 (600036)2018 年 1 月 1 日到 10 日每天的 20 日收盘均价
MySQL8:
with t as (select *,row_number() over(order by tdate) rn from stktrade where sid='600036'),
t1 as (select * from t where tdate between '2018-01-01' and '2018-01-10')
select t1.tdate, t1.close, avg(t.close) ma20
from t1 join t on t.rn between t1.rn-19 and t1.rn
group by t1.tdate;
集算器SPL:
A | |
1 | =connect("mysql") |
2 | =A1.query@x("select tdate,close from stktrade where sid='600036'order by tdate") |
3 | =A2.pselect@a(tdate>=date("2018-01-01") && tdate<=date("2018-01-10")) |
4 | =A2(A3).derive(A2.calc(A3(#),avg(close[-19:0])):ma20) |
A3: 查找所有符合的记录在A2中的行号
A4: A2(A3)根据A3里的行号从A2中取出对应的记录,然后再派生出新记录,新记录复制原记录的字段及值,并增加一列ma20,其值为A2中原记录的20日收盘均价
9、 列出官方语言最多的国家的名称、人口、元首及官方语言数
MySQL8:
select Name, Population, HeadOfState, top.Num
from world.country
join (
select countrycode, count(*) as num
from world.countrylanguage
where isofficial='T'
group by countrycode
having num = (
select max(summary.n)
from (
select countrycode, count(*) as n
from world.countrylanguage
where isofficial='T'
group by countrycode
) as summary
)
) as top on country.code=top.countrycode;
集算器SPL:
A | |
1 | =connect("mysql") |
2 | =A1.query("select * from world.country") |
3 | =A1.query@x("select * from world.countrylanguage where isofficial='T'") |
4 | =A3.group(CountryCode).maxp@a(~.len()) |
5 | =A4.news(A2.select(Code:CountryCode);Name,Population,HeadOfState,A4.~.len():Num) |
A4: 将将各国语言按 CountryCode 分组,然后取出成员数最多的所有组
A5: A4.news对 A4 中每组循环,每组先在 A2 查找对应的国家记录,然后再构造新记录,Num 字段赋值为 A4 中当前组的成员组
转载于:https://blog.51cto.com/12749034/2374377
SQL 难点解决:循环计算相关推荐
- SQL 难点解决:集合及行号
[摘要] SQL 虽然有集合概念,但对于集合运算.特别是有序集合运算,提供的支持却很有限,经常要采用很费解的思路才能完成,计算效率也不佳.而集算器 SPL 在方面则要直观许多,可以按自然思维习惯写出运 ...
- SQL 难点解决:直观分组
1. 对位分组 示例 1:按顺序分别列出使用 Chinese.English.French 作为官方语言的国家数量 MySQL8: with t(name,ord) as (select 'Ch ...
- 停止计算机sql服务,sql2005 本地计算机上的SQL SERVER服务启动后又停止了解决方法...
本方法主要是解决SQL Server运行过程中出现的"本地计算机上的MSSQLSERVER服务启动后又停止了.一些服务自动停止,如果它们没有什么可做的"解决方法. 笔者ASP运行环 ...
- php要每次循环两个数据库,从前台接收的json数据 2个数组,php同时插入sql数据库,循环要怎么套呢?...
从前台接收的json数据 2个数组,php同时插入sql数据库,循环要怎么套呢? mip版 关注:215 答案:2 悬赏:30 解决时间 2021-01-18 18:47 已解决 2021-01 ...
- 【转】Ubuntu 16.04 安装 CUDA10.1 (解决循环登陆的问题)
转自:Ubuntu 16.04 安装 CUDA10.1 (解决循环登陆的问题) - Hongkai_Ding - 博客园 0. 前言 这里直接用 cuda安装文件同时安装 NVIDIA 驱动和 CUD ...
- c语言计算阶乘的倒数和,for循环计算某个数的阶乘、阶乘和及其倒数的阶乘和...
//4的阶乘 int jc = 4; //定义一个变量用来代表要计算的数值 long jd =1; //定义最终输出的阶乘 for(int i = 1; i <= jc;i++) //定义循环加 ...
- php 解决循环引用,excel循环引用如何解决
excel循环引用如何解决? 方法一 需要找到"excel选项",这个地方在Office 2003版本里的"工具"选项里,而在Office 2007版本里不好找 ...
- 50 个 Redis 必备知识:基础知识,架构、调优和监控知识及难点解决
本文包括:30 个 Redis 基础知识:10个 Redis 架构和运维必懂的知识:Redis 调优.监控知识和10个具体应用难点. 30 个 Redis 基础知识 1.Redis支持哪几种数据类型? ...
- 京东一面:Spring 为何需要三级缓存解决循环依赖,而不是二级缓存?我懵了。。...
欢迎关注方志朋的博客,回复"666"获面试宝典 来源:cnblogs.com/semi-sub/p/13548479.html 前言 bean生命周期 三级缓存解决循环依赖 总结 ...
最新文章
- C语言学习之用牛顿迭代法求下面方程在1.5附近的根: 2x³-4x²+3x-6=0
- 和初学者谈谈如何学好单片机编程技术
- 修复版ZFAKA发卡系统源码 自适应PC+手机端
- 设计模式(十三): 命令模式
- 深度学习13-cnn介绍(卷积神经网络简介)
- Java生成随机常用汉字或姓名
- 如何免费下载百度文库、豆丁网等网站的文档
- hdfs 指令_HDFS 常用命令
- 表情识别android项目,Github项目推荐 | Emotion-recognition 实时表情识别
- python不定积分教学_python 求定积分和不定积分示例
- EnjoyToShare | 考研英语复试口语
- kali工具熟悉——情报分析
- linux系统下下载jenkins
- 国货百雀羚化妆品---大数据分析
- 静态成员和静态成员函数的总结
- JavaScript中的arguments,callee,caller,call,appy
- 众多机械设备工业模型图纸素材一键即可获取
- 一加手机怎么导出照片_换手机照片、通讯录备份太麻烦,一加手机轻松解决
- windows server 2008阿里云ECS服务器安全设置
- 快手校招java一面凉经,快手电商生态Java实习一面(凉)