组合查询:
7.1使用子查询:
嵌套在其他查询中的查询,我们称之为子查询。子查询本身也可能包含一个子查询。子查询也称为内部查询,而包含子查询的语句也称为外部查询。
所有的子查询可以被分为两个类别:子查询和非相关子查询。
- 非相关子查询是独立于外部查询的子查询。子查询总共执行一次,执行完毕后将值传递给外部查询。
- 相关子查询的执行依赖于外部查询的数据,外部查询返回一行,子查询就执行一次。
- 子查询作为计算列:子查询的一个最简单的形式就是内部查询为外部查询的每行返回一个单值结果,他通常作为一个结果插入到一个计算列。select columnA ,(子查询)AS columnB from 表名;
- where子句中的子查询:select columnA from TableA where columnB = (子查询);比如在实际中:select examId,studentOn from exam where studentOn <= (select studentOn from exam where examId = 5) order by studentOn desc;
- 返回多个结果的子查询:当子查询返回多行时,我们可以用in关键字来解决上面出现的问题。select 列A,列B from table1 where 列C in (select 列D from table2);这种做法用起来相当复杂,实际上我们可以使用更简单的语法来执行得到同样的结果,就是使用多表联接join查询。当然子查询不仅仅是在select中使用,在其他的修改、删除、插入中也能使用子查询。
- 在子查询中使用运算符:上面我们学了使用子查询与in运算符来查找字段属于某一组值的行。当然除了in以外还可以使用exists、all、any(或者some。二者是同义词)等运算符。
- 其中exists(翻译为:‘存在’)用来测试子查询是否返回任何结果(不只是特定的结果):exists运算符允许我们查找满足特定条件的行。后面总是跟着一个子查询,只要子查询返回了行,exists的值就为真。比如:查询任何一次考试中分数低于40的学生姓名和id。select Id,Name from student s where exists (select Id from studentExam se where mark <40 and e.Id = es.Id);
- all测试子查询结果集的所有行是满足指定条件:all 运算符与子查询和比较运算符一起使用。如果子查询返回的所有值都满足比较运算,那么比较表达式就为真。如果不是所有值都满足比较运算或子查询没有给外部语句返回行,则返回假。如基本语法:select 列A from 表A where 列A > All (select 列B from 表B);实例:查找出enrollment表中总成绩大于同一个学生的最高考试分数的所有行。select Id,grade from enrollment e where grade > All (select mark from studentExam s where e.Id = s.Id);
- any测试子查询的结果集是否有一行或多行满足指定的条件:any 与 All 的工作方式大体相同,不同的地方在于:在子查询返回值中,只要满足比较运算,那么比较表达式就为真。如果所有值都不满足,则返回假。基本语法:select 列A from 表A where 列A > any (select 列B from 表B);这个查询的意思就是说,从表A中返回列A的值大于表中列B的任何一个值的所在行。也即是说返回比列B中最小值大的行。实例:查询出学生的考分和他们总成绩之间的差异。select Id,grade from enrollment e where grade < any(select mark/2 from studentExam s where e.Id = s.Id);
7.2组合查询数据:
如果我们需要使用多个表中的数据,然后将所有的这些数据或者数据子集组合成一个结果集返回,那么SQL提供了几种运算符允许我们组合多个SQL查询来实现这个用途。这些运算符分别是:union、unionall、intersect、difference。
使用这些的语法如:select 列A,列B from 表A <operator> select 列C,列D from 表B;
使用这些运算符的通用规则是:从一个表中获取的数据必须是和其他表中的数据具有相同的列数目,同时两个表中相对应的列必须是具有相同的数据类型或者至少两个数据类型之间必须存在可能的隐性数据转化,或者提供了显示转换。所以,这些运算符是被设计用来组合有相同结构的不同数据的多个表的内容,而从不同结构的组合数据则要用到变链接技术。
- 使用union运算符:select 列A,列B from 表A union select 列C,列D from 表B;通常union的结果集列名与union运算符中第一个select语句的结果集的列名相同。另一个select语句的结果集列名将被忽略。实际的例子中:比如查询从与某节课相关的professor表和student表中抽取姓名。Sql语句是:
select name,'教授' as role from professor where pId = (select pId from class where cId = 1) union select name,'学生' from student where sId in (select sId from enrollment where cId = 1);
使用union的意义就好比:{1,2,3,4} union {3,4,5,6};结果是:{1,2,3,4,5,6}
2. 保留重复行:SQL不管集合理论的通常规则,使用union all 运算符返回每个数据集的所有成员。而不考虑重复。
如:select 列A,列B from 表A union all select 列C,列D from 表B;如:{1,2,3,4} union all {3,4,5,6};最终的结果是:{1,2,3,4,3,4,5,6}
3. 理解交集和差分:最后的两个只能被oracle支持了。intersect运算符允许仅返回在两个查询都出现的行。如:{1234} intersect {3456} 结果是:{34}。difference 在oracle中使用minus ,此运算符允许返回在一个查询中出现但是不在另一个查询中出现的行。如:{1234} except(or minus){3456};结果是:{1256},排除重复的数,显示不重复的数据并且连重复出现的数据都抹掉。