
点击上方【蓝字】关注我们
场景描述
影院座位预定表 T_SEATS 记录了当前座位的预定情况。如有2个人去影院看演唱会,需满足位置紧邻且至少其中一人靠过道(同一排最左或最右的座位靠过道)的座位组合,结果集按开始座位号从小到大排序。座位示意图如下:
CREATE TABLE `t_seats` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`row_no` int DEFAULT NULL COMMENT '第几排',
`seat` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '座位',
`status` int NOT NULL COMMENT '预定状态 0-未预定 1-已预定',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8
复制
查询结果集,字段顺序及命名如下:开始座位号、结束座位号
数据准备
create table t_seat as (select stack(
20,
1, 1, 16, 0,
2, 1, 17, 0,
3, 1, 18, 1,
4, 1, 19, 0,
5, 1, 20, 1,
6, 2, 11, 1,
7, 2, 12, 0,
8, 2, 13, 0,
9, 2, 14, 1,
10, 2, 15, 0,
11, 3, 8, 0,
12, 3, 9, 1,
13, 3, 10, 0,
14, 4, 5, 0,
15, 4, 6, 0,
16, 4, 7, 1,
17, 5, 3, 0,
18, 5, 4, 0,
19, 6, 1, 1,
20, 6, 2, 0
) as (id, row_num, seat, status)
)
;
复制
问题分析
方法1:利用lag()及lead()分析函数求解
第一步:利用lag()及lead()函数求出左边座位、右边座位,及左边座位状态、右边座位状态,进行辅助判断。
select id
, row_num
, seat
, status
, lag(seat) over (partition by row_num order by seat) lag_seat
, lead(seat) over (partition by row_num order by seat) lead_seat
, lag(status, 1, status) over (partition by row_num order by seat) lag_status
, lead(status, 1, status) over (partition by row_num order by seat) lead_status
from t_seat
复制
紧邻判断:即当前seat值 +1 = lead_seat即可 状态判断:无论获取的lag_seat还是lead_seat都必须是未被预定的,即(lag_status + lead_status) = 0
case
when (lag_seat + lead_seat) is null and (lag_status + lead_status) = 0 and seat + 1 = lead_seat
then 1 end flg
复制
完整的SQL如下:
select row_num
, seat
, lead_seat
from (select id
, row_num
, seat
, lag_seat
, lead_seat
, case
when (lag_seat + lead_seat) is null and (lag_status + lead_status) = 0 and seat + 1 = lead_seat
then 1 end flg
from (select id
, row_num
, seat
, status
, lag(seat) over (partition by row_num order by seat) lag_seat
, lead(seat) over (partition by row_num order by seat) lead_seat
, lag(status, 1, status) over (partition by row_num order by seat) lag_status
, lead(status, 1, status) over (partition by row_num order by seat) lead_status
from t_seat) t
where status = 0) t
where flg = 1;
复制
SQL可简化为:
select row_num
, seat
, lead_seat
from (select
row_num
, seat
, status
, lag(seat) over (partition by row_num order by seat) lag_seat
, lead(seat) over (partition by row_num order by seat) lead_seat
, lag(status, 1, status) over (partition by row_num order by seat) lag_status
, lead(status, 1, status) over (partition by row_num order by seat) lead_status
from t_seat) t
where
case when (lag_seat + lead_seat) is null and (lag_status + lead_status) = 0 and seat + 1 = lead_seat then 1 end = 1
复制
方法2:转换成字符串序列进行分析
range between current row and 1 following
复制
select row_num
, seat
, collect_list(seat)
over (partition by row_num order by seat range between current row and 1 following) seat_list
from t_seat
where status = 0
复制
第二步:计算同一排座位中的最大最小 值,依此来判断是否靠近过道
select row_num
, min(seat) min_seat
, max(seat) max_seat
from t_seat
group by row_num
复制
array_contains(seat_list, min_seat) or array_contains(seat_list, max_seat) 为true
复制
完整的SQL如下:
select t.row_num
, seat_list[0] start_num
, seat_list[1] end_num
from (select row_num
, seat
, collect_list(seat)
over (partition by row_num order by seat range between current row and 1 following) seat_list
from t_seat
where status = 0) t
left join (select row_num
, min(seat) min_seat
, max(seat) max_seat
from t_seat
group by row_num) t2
on t.row_num = t2.row_num
where size(seat_list) = 2
and (array_contains(seat_list, min_seat) or array_contains(seat_list, max_seat))
复制
方法3:自关联求解
具体SQL如下:
select a.row_num
, start_num
, end_num
from (SELECT a.row_num row_num
, a.seat start_num
, b.seat end_num
FROM t_seat a,
t_seat b
where a.row_num = b.row_num
and a.seat + 1 = b.seat
and a.status = 0
and b.status = 0) a
left join
(select row_num
, min(seat) min_seat
, max(seat) max_seat
from t_seat
group by row_num) b
on a.row_num = b.row_num
where greatest(start_num, end_num) = max_seat
or least(start_num, end_num) = min_seat
复制
小结
猜你喜欢



公众号:会飞一十六
扫码关注 了解更多内容
点个 在看 你最好看
文章转载自会飞的一十六,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
云和恩墨钟浪峰:安全生产系列之SQL优化安全操作
墨天轮编辑部
214次阅读
2025-03-31 11:08:20
同一条SQL开发环境比生产环境执行速度快案例分享
董小姐
186次阅读
2025-03-20 06:50:49
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
132次阅读
2025-04-17 17:02:24
Before & After:SQL整容级优化
薛晓刚
82次阅读
2025-04-14 22:08:44
GoldenDB数据库SQL画像功能,助力实现精准SQL诊断
Whill
71次阅读
2025-03-28 18:52:43
让AI读懂Oracle!使用OCI A10微调大模型生成融合查询SQL
甲骨文云技术
65次阅读
2025-03-19 11:21:10
金点分享 | GoldenDB数据库智能SQL限流,让算力精准赋能业务
Whill
64次阅读
2025-03-28 18:53:07
Mysql/Oracle/Postgresql快速批量生成百万级测试数据sql
hongg
52次阅读
2025-04-07 15:32:54
Oracle数据库常用脚本(七)
lh11811
49次阅读
2025-04-01 08:57:44
Oracle DBA 必备!这份高效运维的“秘籍”,高频实用 SQL 一网打尽
青年数据库学习互助会
49次阅读
2025-03-31 10:03:00