SQL进阶-10-用SQL处理数列
在关系型数据库的数据结构中,默认是不考虑数据的顺序。处理有序集合在SQL中不能直接实现,但是可以通过集合和谓词来间接实现处理有序数据的需求。
重要的知识点:用存在量化的否定形式来解决全称量化问题
需求1-生成连续编号
需求
不使用数据库中自带的函数,实现任意长的连续编号序列,比如生成0-99的100个连续编号
SQL实现
先解决一个问题:00-99
这100
个数字中,0,1,2……9
这10
个数字分别出现了多少次?
从下面的表中可以明显看出来:每个数字出现了20次
- 生成一个
digits
表,用来存储各个数位上的数字,因为不管多大的数字都可以由0-9
这10
个数字组成
- 通过对两个Digits集合求笛卡尔积得出0-99的数字
1 | select D1.digit + (D2.digit * 10) as seq -- 两位数 |
什么是笛卡尔积
通过交叉联结求出集合的笛卡尔积:实现所有可能的组合
需求2-生成1-542的编号
1 | select D1.digit + (D2.digit * 10) + (D3.digit * 100) as seq |
生成视图调用
1 | -- 事先将结果生成视图,方便后续调用 |
需求3-求解全部的缺失值
如何从已知的序列中求出全部的缺失值?我们借助上面生成的视图:
1 | -- except版本 |
火车问题-连续空位
我们假设3个人一起去旅行,准备预订这列火车的车票,要求是从1-15号的座位中选择出连续的3个空位置,我们把连续的整数构成的集合称之为序列,这样的序列中不能出现缺失的编号。
满足要求的序列:
根据上面的图形,我们发现满足要求的序列:以n为起点,n+(3-1)=n+2为终点的作为全部是未预定状态
SQL实现-不考虑换排
1 | -- 不考虑换排 |
:head_cnt
表示需要的空位个数的参数,通过给参数赋值能够应对任意多个人的预约。上面代码的主要工作:
- 找到起点和终点
- 起点和终点之间的座位都是未预定的状态
全称量化问题:将所有满足条件P转成不存在不满条件P的行
SQL实现-考虑换排
给表中的数据加上了行编号row_id
因为发生换排,9,10,11
不再符合要求。因此,为了解决换排问题,需要保证:全部都在同一排
1 | -- 考虑换排 |
肯定等于双重否定
火车问题—最多坐几个人
按照空位的问题,最多能够坐下几个人:求出最长的序列。下图中的2-5号就是满足要求的
要保证从座位A到座位B全部是未预定的状态,必须满足3个条件:
- 起点和终点之间的所有座位都是未预定状态
- 起点之前的座位不是未预定(不能往前延伸)
- 终点之后的座位不是未预定(不能往后扩展)
SQL实现
生成所有序列的视图:存在量化的否定形式来表达全称量化
1 | -- 1、创建视图 |
求出最长的序列:
1 | select start_seat,'~',end_seat,seat_cnt |