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; 
相关推荐
一只小bit43 分钟前
Redis哨兵机制、主从复制与集群搭建与维护
数据库·redis·bootstrap
zlwool7 小时前
图纸管理选型避坑指南
数据库·erp·设备erp·非标机械
小灰灰搞电子8 小时前
完全驾驭 Qt 与数据库:C++ ORM 框架 QxOrm 原理与实践指南
数据库·c++·qt
软件聚导航10 小时前
「聚小软 AI 助手」技术升级:从数据库检索到 RAG 知识库问答
前端·数据库·mysql·微信小程序·小程序·ai编程·rag
2601_9609067211 小时前
1X发布自己的世界模型1XWM
mysql·mongodb·rabbitmq·memcached
学习星球11 小时前
单调栈——从“找下一个更大的“到柱状图中的最大矩形
数据库·c++·算法·leetcode·xcode
GoppViper11 小时前
RDF资源描述框架深度解析:语义Web的数据基石与实战逻辑
前端·数据库
2601_9621741712 小时前
Redis 简介
数据库·redis·wpf
夜雪一千12 小时前
MySQL 各种数据同步方案全梳理:从简单复制到异构同步实战
数据库·mysql
ruleslol12 小时前
MySQL: OR查询为什么会导致索引失效
mysql