写在前面

关系模型的数据结构里,并没有顺序的概念,但SQL处理有序集合也有坚实的理论基础

生成连续编号

  1. --生成连续编号
  2. CREATE TABLE Digits
  3. (digit INTEGER PRIMARY KEY);
  4. INSERT INTO Digits VALUES (0);
  5. INSERT INTO Digits VALUES (1);
  6. INSERT INTO Digits VALUES (2);
  7. INSERT INTO Digits VALUES (3);
  8. INSERT INTO Digits VALUES (4);
  9. INSERT INTO Digits VALUES (5);
  10. INSERT INTO Digits VALUES (6);
  11. INSERT INTO Digits VALUES (7);
  12. INSERT INTO Digits VALUES (8);
  13. INSERT INTO Digits VALUES (9);
  1. -- 创建00-99的序列
  2. SELECT (D1.digit + D2.digit * 10) AS seq
  3. FROM Digits AS D1 CROSS JOIN Digits AS D2
  4. ORDER BY seq;
  5. -- 创建1542的序列
  6. SELECT (D1.digit + D2.digit * 10 + D3.digit * 100) AS seq
  7. FROM Digits AS D1,Digits AS D2,Digits AS D3
  8. WHERE (D1.digit + D2.digit * 10 + D3.digit * 100) BETWEEN 1 AND 542
  9. ORDER BY seq;
  1. CREATE VIEW Sequence (seq) AS
  2. SELECT D1.digit + (D2.digit * 10 ) + (D3.digit * 100)
  3. FROM Digits D1,Digits D2,Digits D3;
  4. SELECT seq FROM Sequence WHERE seq BETWEEN 1 AND 100 ORDER BY seq;

求全部的缺失编号

  1. -- EXCEPT
  2. SELECT seq FROM Sequence WHERE seq BETWEEN 1 AND 12
  3. EXCEPT (SELECT * FROM SeqTbl);
  4. -- NOT IN
  5. SELECT seq FROM Sequence WHERE seq BETWEEN 1 AND 12 AND seq
  6. NOT IN (SELECT * FROM SeqTbl);
  1. -- 动态地指定连续编号范围的SQL语句
  2. SELECT seq FROM Sequence WHERE seq BETWEEN (SELECT MIN(seq) FROM SeqTbl) AND (SELECT MAX(seq) FROM SeqTbl) EXCEPT (SELECT * FROM SeqTbl);

三个人能坐得下吗?

  1. --三个人能坐得下吗?
  2. CREATE TABLE Seats
  3. ( seat INTEGER NOT NULL PRIMARY KEY,
  4. status CHAR(6) NOT NULL
  5. CHECK (status IN ('未预订', '已预订')) );
  6. INSERT INTO Seats VALUES (1, '已预订');
  7. INSERT INTO Seats VALUES (2, '已预订');
  8. INSERT INTO Seats VALUES (3, '未预订');
  9. INSERT INTO Seats VALUES (4, '未预订');
  10. INSERT INTO Seats VALUES (5, '未预订');
  11. INSERT INTO Seats VALUES (6, '已预订');
  12. INSERT INTO Seats VALUES (7, '未预订');
  13. INSERT INTO Seats VALUES (8, '未预订');
  14. INSERT INTO Seats VALUES (9, '未预订');
  15. INSERT INTO Seats VALUES (10, '未预订');
  16. INSERT INTO Seats VALUES (11, '未预订');
  17. INSERT INTO Seats VALUES (12, '已预订');
  18. INSERT INTO Seats VALUES (13, '已预订');
  19. INSERT INTO Seats VALUES (14, '未预订');
  20. INSERT INTO Seats VALUES (15, '未预订');
  1. -- 找出需要的空位(1):不考虑座位的换排
  2. SELECT S1.seat AS start_seat,'~',S2.seat AS end_seat
  3. FROM Seats S1,Seats S2
  4. WHERE S2.seat = S1.seat + 2 AND NOT EXISTS
  5. (SELECT * FROM Seats S3 WHERE S3.seat BETWEEN S1.seat AND S2.seat AND S3.status <> '未预订');
  1. --考虑座位的折返
  2. CREATE TABLE Seats2
  3. ( seat INTEGER NOT NULL PRIMARY KEY,
  4. row_id CHAR(1) NOT NULL,
  5. status CHAR(6) NOT NULL
  6. CHECK (status IN ('未预订', '已预订')) );
  7. INSERT INTO Seats2 VALUES (1, 'A', '已预订');
  8. INSERT INTO Seats2 VALUES (2, 'A', '已预订');
  9. INSERT INTO Seats2 VALUES (3, 'A', '未预订');
  10. INSERT INTO Seats2 VALUES (4, 'A', '未预订');
  11. INSERT INTO Seats2 VALUES (5, 'A', '未预订');
  12. INSERT INTO Seats2 VALUES (6, 'B', '已预订');
  13. INSERT INTO Seats2 VALUES (7, 'B', '已预订');
  14. INSERT INTO Seats2 VALUES (8, 'B', '未预订');
  15. INSERT INTO Seats2 VALUES (9, 'B', '未预订');
  16. INSERT INTO Seats2 VALUES (10,'B', '未预订');
  17. INSERT INTO Seats2 VALUES (11,'C', '未预订');
  18. INSERT INTO Seats2 VALUES (12,'C', '未预订');
  19. INSERT INTO Seats2 VALUES (13,'C', '未预订');
  20. INSERT INTO Seats2 VALUES (14,'C', '已预订');
  21. INSERT INTO Seats2 VALUES (15,'C', '未预订');
  1. -- 找出需要的空位(2):考虑座位的换排
  2. SELECT S1.seat AS start_seat,'~',S2.seat AS end_seat
  3. FROM Seats2 S1,Seats2 S2
  4. WHERE S2.seat = S1.seat + 2 AND NOT EXISTS
  5. (SELECT * FROM Seats2 S3 WHERE S3.seat BETWEEN S1.seat AND S2.seat AND (S3.status <> '未预订' OR S3.row_id <> S1.row_id));

最多能坐下多少人

  1. --最多能坐下多少人?
  2. CREATE TABLE Seats3
  3. ( seat INTEGER NOT NULL PRIMARY KEY,
  4. status CHAR(6) NOT NULL
  5. CHECK (status IN ('未预订', '已预订')) );
  6. INSERT INTO Seats3 VALUES (1, '已预订');
  7. INSERT INTO Seats3 VALUES (2, '未预订');
  8. INSERT INTO Seats3 VALUES (3, '未预订');
  9. INSERT INTO Seats3 VALUES (4, '未预订');
  10. INSERT INTO Seats3 VALUES (5, '未预订');
  11. INSERT INTO Seats3 VALUES (6, '已预订');
  12. INSERT INTO Seats3 VALUES (7, '未预订');
  13. INSERT INTO Seats3 VALUES (8, '已预订');
  14. INSERT INTO Seats3 VALUES (9, '未预订');
  15. INSERT INTO Seats3 VALUES (10, '未预订');
  1. -- 先生成存储了所有序列的视图
  2. CREATE VIEW Sequences(start_seat,end_seat,seat_cnt) AS
  3. SELECT S1.seat AS start_seat,S2.seat AS end_seat,S2.seat-S1.seat + 1 AS seat_cnt
  4. FROM Seats3 S1,Seats3 S2
  5. WHERE S1.seat < S2.seat
  6. AND NOT EXISTS (SELECT * FROM Seats3 S3 WHERE (S3.seat BETWEEN S1.seat AND S2.seat AND S3.status<> '未预订') OR (S3.seat = S2.seat + 1 AND S3.status = '未预订') OR (S3.seat = S1.seat - 1 AND S3.status = '未预订'));
  7. -- 取出最长的序列
  8. SELECT start_seat,end_seat,seat_cnt FROM
  9. Sequences WHERE seat_cnt = (SELECT MAX(seat_cnt) FROM Sequences);

单调递增和单调递减

  1. --单调递增和单调递减
  2. CREATE TABLE MyStock
  3. (deal_date DATE PRIMARY KEY,
  4. price INTEGER );
  5. INSERT INTO MyStock VALUES ('2007-01-06', 1000);
  6. INSERT INTO MyStock VALUES ('2007-01-08', 1050);
  7. INSERT INTO MyStock VALUES ('2007-01-09', 1050);
  8. INSERT INTO MyStock VALUES ('2007-01-12', 900);
  9. INSERT INTO MyStock VALUES ('2007-01-13', 880);
  10. INSERT INTO MyStock VALUES ('2007-01-14', 870);
  11. INSERT INTO MyStock VALUES ('2007-01-16', 920);
  12. INSERT INTO MyStock VALUES ('2007-01-17', 1000);
  1. -- 生成起点到终点的组合
  2. SELECT My1.deal_date,My2.deal_date
  3. FROM MyStock AS My1,MyStock AS My2
  4. WHERE My1.deal_date < My2.deal_date
  5. AND NOT EXISTS
  6. (SELECT * FROM MyStock AS My3,MyStock AS My4
  7. WHERE My3.deal_date BETWEEN My1.deal_date AND My2.deal_date
  8. AND My3.deal_date BETWEEN My1.deal_date AND My2.deal_date
  9. AND My3.deal_date < My4.deal_date
  10. AND My3.price >= My4.price);
  1. --排除掉子集,只取最长的时间区间
  2. SELECT MIN(start_date) AS start_date, /* 最大限度地向前延伸起点 */
  3. end_date
  4. FROM (SELECT S1.deal_date AS start_date,
  5. MAX(S2.deal_date) AS end_date /* 最大限度地向后延伸终点 */
  6. FROM MyStock S1, MyStock S2
  7. WHERE S1.deal_date < S2.deal_date
  8. AND NOT EXISTS
  9. (SELECT *
  10. FROM MyStock S3, MyStock S4
  11. WHERE S3.deal_date BETWEEN S1.deal_date AND S2.deal_date
  12. AND S4.deal_date BETWEEN S1.deal_date AND S2.deal_date
  13. AND S3.deal_date < S4.deal_date
  14. AND S3.price >= S4.price)
  15. GROUP BY S1.deal_date) TMP
  16. GROUP BY end_date
  17. ORDER BY start_date;

小结

  • SQL处理数据的方法有两种
  • 第一种把数据看成忽略了顺序的集合
  • 第二种把数据看成有序的集合,此时的基本方法如下:
    • 首先自连接生成起点到终点的集合
    • 其次在子查询中描述内部的各个元素之间必须满足的关系
  • 要在SQL中表达全称量化时,需要将全称量化命题转化为存在量化命题的否定形式,并使用NOT EXISTS谓词。

练习题

  1. /* 练习题1-9-1:求所有的缺失编号——NOT EXISTS和外连接
  2. NOT EXISTS版 */
  3. SELECT seq
  4. FROM Sequence N
  5. WHERE seq BETWEEN 1 AND 12
  6. AND NOT EXISTS
  7. (SELECT *
  8. FROM SeqTbl S
  9. WHERE N.seq = S.seq );
  1. /* 练习题1-9-1:求所有的缺失编号——NOT EXISTS和外连接
  2. NOT EXISTS版 */
  3. SELECT N.seq
  4. FROM Sequence N LEFT OUTER JOIN SeqTbl S
  5. ON N.seq = S.seq
  6. WHERE N.seq BETWEEN 1 AND 12
  7. AND S.seq IS NULL;
  1. /* 练习题1-9-2:求序列——面向集合的思想 */
  2. SELECT S1.seat AS start_seat, '~' , S2.seat AS end_seat
  3. FROM Seats S1, Seats S2, Seats S3
  4. WHERE S2.seat = S1.seat + (:head_cnt -1)
  5. AND S3.seat BETWEEN S1.seat AND S2.seat
  6. GROUP BY S1.seat, S2.seat
  7. HAVING COUNT(*) = SUM(CASE WHEN S3.status = '未预订' THEN 1 ELSE 0 END);
  1. /* 坐位有换排时 */
  2. SELECT S1.seat AS start_seat, ' ~ ' , S2.seat AS end_seat
  3. FROM Seats2 S1, Seats2 S2, Seats2 S3
  4. WHERE S2.seat = S1.seat + (:head_cnt -1)
  5. AND S3.seat BETWEEN S1.seat AND S2.seat
  6. GROUP BY S1.seat, S2.seat
  7. HAVING COUNT(*) = SUM(CASE WHEN S3.status = '未预订'
  8. AND S3.row_id = S1.row_id THEN 1 ELSE 0 END);
  1. /* 练习题1-9-3:求所有的序列——面向集合的思想 */
  2. SELECT S1.seat AS start_seat,
  3. S2.seat AS end_seat,
  4. S2.seat - S1.seat + 1 AS seat_cnt
  5. FROM Seats3 S1, Seats3 S2, Seats3 S3
  6. WHERE S1.seat <= S2.seat /* 第一步:生成起点和终点的组合 */
  7. AND S3.seat BETWEEN S1.seat - 1 AND S2.seat + 1
  8. GROUP BY S1.seat, S2.seat
  9. HAVING COUNT(*) = SUM(CASE WHEN S3.seat BETWEEN S1.seat AND S2.seat
  10. AND S3.status = '未预订' THEN 1 /* 条件1 */
  11. WHEN S3.seat = S2.seat + 1 AND S3.status = '已预订' THEN 1 /* 条件2 */
  12. WHEN S3.seat = S1.seat - 1 AND S3.status = '已预订' THEN 1 /* 条件3 */
  13. ELSE 0 END);

SQL进阶系列之9用SQL处理数列的更多相关文章

  1. SQL进阶系列之11让SQL飞起来

    写在前面 SQL的性能优化是数据库使用者必须面对的重要问题,本节侧重SQL写法上的优化,SQL的性能同时还受到具体数据库的功能特点影响,这些不在本节讨论范围之内 使用高效的查询 参数是子查询时,使用E ...

  2. SQL进阶系列之7用SQL进行集合运算

    写在前面 集合论是SQL语言的根基,因为这种特性,SQL也被称为面向集合语言 导入篇:集合运算的几个注意事项 注意事项1:SQL能操作具有重复行的集合(multiset.bag),可以通过可选项ALL ...

  3. [SQL SERVER系列]读书笔记之SQL注入漏洞和SQL调优

    最近读了程序员的SQL金典这本书,觉得里面的SQL注入漏洞和SQL调优总结得不错,下面简单讨论下SQL注入漏洞和SQL调优. 1. SQL注入漏洞 由于“'1'='1'”这个表达式永远返回 true, ...

  4. Linq To Sql进阶系列(六)用object的动态查询与保存log篇

    动态的生成sql语句,根据不同的条件构造不同的where字句,是拼接sql 字符串的好处.而Linq的推出,是为了弥补编程中的 Data != Object 的问题.我们又该如何实现用object的动 ...

  5. SQL进阶系列之12SQL编程方法

    写在前面 KISS -- keep it sweet and simple 表的设计 注意命名的意义 英文字母 + 阿拉伯数字 + 下划线"_" 属性和列 编程的方针 写注释 注意 ...

  6. SQL进阶系列之10HAVING子句又回来了

    写在前面 HAVING子句的处理对象是集合而不是记录 各队,全队点名 --各队,全体点名! CREATE TABLE Teams (member CHAR(12) NOT NULL PRIMARY K ...

  7. SQL进阶系列之8EXISTS谓词的用法

    写在前面 支撑SQL和关系数据库的基础理论:数学领域的集合论和逻辑学标准体系的谓词逻辑 理论篇 什么是谓词?谓词是返回值为真值(true false unknown)的函数 关系数据库里,每一个行数据 ...

  8. SQL进阶系列之6用关联子查询比较行与行

    写在前面 使用SQL对同一行数据进行列间的比较很简单,只需要在WHERE子句里写上比较条件就可以了,对于不同行数据进行列间比较需要使用自关联子查询. 增长.减少.维持现状 需要用到行间比较的经典场景是 ...

  9. SQL进阶系列之5外连接的用法

    写在前面 SQL本身是作为一种数据提取工具而出现,使用SQL生成各种定制化报表和非定制化报表并非SQL原本用途的功能,但这并不意味着SQL无法实现这些功能. 用外连接进行行列转换(1)(行 → 列): ...

随机推荐

  1. (三)Java数据结构和算法——冒泡、选择、插入排序算法

    一.冒泡排序 冒泡算法的运作规律如下: ①.比较相邻的元素.如果第一个比第二个大,就交换他们两个. ②.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.这步做完后,最后的元素会是最大的数( ...

  2. json_encode不自动转义斜杠“/”的方法

    默认的情况之下使用 json_encode 对数组进行 json 格式的转换时候会自动的将数据中含有斜杠的字符串进行转义,如图 两种解决办法   其一,正则替换: $a = str_replace(& ...

  3. 超详尽-QThread的正确使用姿势-以及信号槽的跨线程使用

    贴上两篇博文 一.http://www.cnblogs.com/findumars/p/5031239.html 循序渐进介绍了,怎样正确的让槽函数工作在子线程中. 同时介绍了信号槽的绑定与线程的关系 ...

  4. 【常用技巧】标准模板库(STL)

    [常用技巧]标准模板库(STL) 在前几个章节中我们已经使用了诸如队列.堆.堆栈.vector 等标准模板库中的模板,切身感受到了它给我们带来的极大便利.在本节中,我们还要介绍两种标准模板——stri ...

  5. IDEA更改JavaScript版本

    最好改两个地方 File -> File -> -- --

  6. CentOS 5 源

    # The mirror system uses the connecting IP address of the client and the # update status of each mir ...

  7. UML部署图

    部署图与组件图密切相关,部署图是用来描述软件组件部署的硬件组件:而组件图是用来描述组件和显示了它们是如何在硬件中部署. 部署图通常用来帮助理解分布式系统,一个系统模型只有一个部署图. 部署图用于可视化 ...

  8. 第4课,python 条件语句if用法

    主题: 智能对话程序的设计 前言: 在编程中存在三大逻辑结构:顺序结构,分支结构(用条件语句if构成),循环结构.其中循环结构能完成,重复次数多,庞大的工作: 分支结构优势不在完成的多,但占有重要位置 ...

  9. DS AVL树详解

    先说说二叉搜索树: 是有序的二叉树,根值>左节点值,右节点值>根值. 如果要查找某个值,二叉搜索树和二分查找一样,每进行一次值比较,就会减少一半的遍历区间. 但是,如果树插入的值一直递增/ ...

  10. golang 堆排序

    堆排序的思想  因为堆的形式是完全二叉树,跟数组的索引形成映射,可以使用数组保存.先构建最大(小)堆,根结点就是最大(小)值,删除根结点之后的节点重新构建堆,依此顺序,即可完成堆排序. 代码实现 pa ...