SQL 处理数列

在关系模型的数据结构中,并没有"顺序"这一概念。因此,基于它实现的关系数据库中的表和视图的行和列也必然没有顺序。

1 处理数列

1.1 实践

1.1.1 生成连续编号

图 t_num 数据库源与目标视图v_seq

需求:根据0~9 这10个数,生成0~999的连续按升序排列的数列,并创建视图v-seq。

sql 复制代码
create view v_seq(seq) as 
select n1.num + n2.num * 10 + n3.num * 100 as seq
from t_num n1
cross join t_num n2 
cross join t_num n3 
order by seq 

1.1.2 求全部的缺失编号

表 连续编号t_seq_num 表 及期望输出

需求:找出t_seq_num 表中缺失的编号。

sql 复制代码
-- except
select seq 
from v_seq 
where seq between (select min(seq) from t_seq_num) and (select max(seq) from t_seq_num)
except 
select seq 
from t_seq_num;

-- NOT EXISTS 
select seq 
from v_seq v
where seq between (select min(seq) from t_seq_num) and (select max(seq) from t_seq_num)
and not exists 
(
select *
from t_seq_num s 
where s.seq = v.seq 
);

-- 连接
select t1.seq 
from (
select seq 
from v_seq v
where seq between (select min(seq) from t_seq_num) and (select max(seq) from t_seq_num)
) t1 
left join t_seq_num t2 on t1.seq = t2.seq 
where t2.seq is null; 

1.1.3 3个人能坐得下吗

图 座位预定t_seats 表及期望输出

需求:找出座位号连续3个为"未预定的组合"。

sql 复制代码
-- not exists
select s1.seat as begin_seat, s2.seat as end_seat 
from t_seats s1
cross join t_seats s2 
where s2.seat = s1.seat + 2 
and not exists (
select *
from t_seats s3 
where s3.seat between s1.seat and s2.seat 
and s3.status != '未预定'
);

-- 窗口函数
select *
from (
select seat as begin_seat,
max(seat) over(order by seat rows between 2 following and 2 following) as end_seat
from t_seats 
where `status` = '未预定'
) tmp 
where end_seat - begin_seat = 2;

-- group by 
select s1.seat as begin_seat,s2.seat as end_seat 
from t_seats s1 
cross join t_seats s2 
cross join t_seats s3 
where s2.seat = s1.seat + 2 and s3.seat between s1.seat and s2.seat 
group by s1.seat,s2.seat
having count(*) = sum(case when s3.status = '未预定' then 1 else 0 end);

1.1.4 有换排的座位, 3个人能坐下吗?

图 有换排的座位预定情况t_seats2表及期望输出

需求:找出同排,且连续3个座位号都为未预定的组合。

sql 复制代码
-- not exists
select s1.seat as begin_seat,s2.seat as end_seat
from t_seats2 s1 
cross join t_seats2 s2 
where s2.seat = s1.seat + 2 
and not exists (
select * 
from t_seats2 s3 
where s3.seat between s1.seat and s2.seat 
and ( s3.line_id != s1.line_id or s3.status != '未预定' )
);

-- 窗口函数 
select *
from (
select seat as begin_seat, 
max(seat) over (partition by line_id order by seat rows between 2 following and 2 following) as end_seat
from t_seats2
where status = '未预定'
) temp
where end_seat - begin_seat = 2; 

-- group by 
select s1.seat as begin_seat,s2.seat as end_seat 
from t_seats2 s1
cross join t_seats2 s2
cross join t_seats2 s3
where s2.seat = s1.seat + 2 and s3.seat between s1.seat and s2.seat 
group by s1.seat,s2.seat 
having count(*) = SUM(case when s3.line_id = s1.line_id and s3.status = '未预定' then 1 else 0 end);

1.1.5 单调递增区间

图 股票每日价格t_stocks表及期望输出

需求:找出单调递增区间。

sql 复制代码
-- 查找出与前日相比,股价上市的交易日
create view v_up_stocks as 
select *
from 
(
select 
deal_date,price,
case sign(price - max(price) over(order by deal_date rows between 1 preceding and 1 preceding)) 
when 1 then 'up'
when 0 then 'eq'
when -1 then 'down'
else '~'
end as sign,
row_number() over (order by deal_date) as row_num
from t_stocks
) tmp
where sign = 'up'

图 上市的股票交易日信息视图v_up_stocks

sql 复制代码
select min(deal_date) as begin_date,max(deal_date) as end_date
from (
select s1.deal_date,min(s1.row_num) - count(s1.deal_date) as gap 
from v_up_stocks s1 
cross join v_up_stocks s2 
where s1.deal_date >= s2.deal_date 
group by s1.deal_date
) tmp
group by gap 
order by begin_date; 
相关推荐
怕什么真理无穷5 分钟前
mysql server 9.4 windows安装教程(sqlyog 下载)
数据库
Olrookie11 分钟前
MySQL运维常用SQL
运维·数据库·sql·mysql·dba
数据库生产实战21 分钟前
ORACLE 19C ADG环境 如何快速删除1.8TB的分区表?有哪些注意事项?
数据库·oracle
blackorbird38 分钟前
使用 Overpass Turbo 查找监控摄像头
运维·服务器·数据库·windows
IT永勇42 分钟前
SQLite数据库基本操作
数据库·sqlite·嵌入式开发·增删改查·关系型数据库
洋不写bug44 分钟前
数据库的创建,查看,修改,删除,字符集编码和校验操作
android·数据库·adb
想ai抽1 小时前
吃透大数据算法-算法地图(备用)
大数据·数据库·spark
weixin_307779131 小时前
Clickhouse导出库的表、视图、用户和角色定义的SQL语句
开发语言·数据库·算法·clickhouse·自动化
流星白龙1 小时前
【Qt】7.信号和槽_connect函数用法(1)
开发语言·数据库·qt
码界奇点1 小时前
平替MongoDB金仓多模数据库在电子证照国产化中的实践与优势
数据库·mongodb·社交电子·里氏替代原则