??SQL作用在关系上的union、intersect和except运算对应于数学集合论中的交,并和差,我们现在来构造包含在两个集合上使用union, intersect和except运算的查询。
(select coursr_id
from section
where semester='Fall' and year=2017)
union
(select coursr_id
from section
where semester='spring' and year=2018)
(select coursr_id
from section
where semester='Fall' and year=2017)
union all
(select coursr_id
from section
where semester='spring' and year=2018)
(select coursr_id
from section
where semester='Fall' and year=2017)
intersect
(select coursr_id
from section
where semester='spring' and year=2018)
??如果想保留所有重复,则用intersect all替换intersect。
(select coursr_id
from section
where semester='Fall' and year=2017)
except
(select coursr_id
from section
where semester='spring' and year=2018)
如果想保留所有重复,则用except all替换except。
??空值给关系运算带来了特殊的问题,包括算术运算、比较运算和集合运算。SQL将涉及空置的各种比较运算结果都视为unknown,这创建了True和False之外的第三个逻辑谓词。
针对空值的一些处理(where子句,select子句等)
? 聚集函数是以值的一个集合(集或多重集)为输入、返回单个值的函数。SQL提供了五个固有聚集函数:
select 函数符号(<distinct> 目标列表达式) <as 新属性名>
from 关系名
<where P>
实质上是返回输入的一个汇集结果,一般常用上述五种函数。
??有时候我们不仅希望将聚集函数作用在单个元组集上,而且也希望将其作用到一组元组集上;在SQL中可用group by子句实现这个愿望。group by子句中给出的一个或多个属性是用来构造分组的。在group by子句中的所有属性上取值相同的元组将被分在一个组中。 示例如下:
group by 列名 <having 条件表达式>
注意事项
出现在select语句中,没有被聚集的属性必须出现在group by子句中 (分组属性,组内值相同)
select dept_name, avg(salary)as avg_salary
from instructor
group by dept_name
having avg(salary)>42000;
出现在having子语中,但没有被聚集的属性必须出现在group by子句中 (小组筛选,也必须用分组属性)
? having用于对分组设定限定条件
select course_id,sec_id,semester,year,avg(tot_cred)
from takes natural join student
where year=2009
group by course_id,semester,year,sec_id
having count(ID) >= 2
select SAGE,count(SNO)
from S
where SEX = ‘男’
group by SAGE
having count(*) > 50
??总而言之,SQL按以下原则处理空值:除了 count(*)外所有的聚集函数都忽略输入集合中的空值。由于空值被忽略,有可能造成参加函数运算的输入值集合为空集。规定空集的count运算值为0,其他所有聚集运算在输入为空集的情况下返回一个空值。
??SQL提供嵌套子查询机制。子查询是嵌套在另一个查询中的select-from-where表达式。子查询嵌套在where子句中,通常用于对集合的成员资格、集合的比较以及集合的基数进行检查。
??SQL允许测试元组在关系中的成员资格。连接词in测试元组是否是集合中的成员,集合是由select子句产生的一组值构成的。连接词not in则测试元组是否不是集合中的成员。
select distinct course_id
from section
where semester= 'Fall' and year=2017 and
course_id in (select course_id
from section
where semester = 'Spring' and year=2018)
select distinct course_id
from section
where semester= 'Fall' and year=2017 and
course_id not in (select course_id
from section
where semester = 'Spring' and year=2018)
select *
from S
where SNAME in ('张军','王红')
select distinct name
from instructor
where name not in ('Mozart','Einstein')
select count(distinct ID)
from takes
where (course_id,sec_id,semester,year) in (select course_id,sec_id,semester,year
from teaches
where teaches.ID=10101)
短语“至少比某一个要大”在SQL中用> some表示。考虑下面的语句转换
select name
from instructor
where salary > some (select salary
from instructor
where dept_name='Biology')
结构>all对应于词组“比所有的都大”。
select SNO
from SC
group by SNO
having avg(GRADE) >= all (select avg(GRADE)
from SC
group by SNO)
??SQL还有一个特性可测试一个子查询的结果中是否存在元组。exists结构在作为参数的子查询非空时返回true值。
??我们可以用not exists结构测试子查询结果集中是否不存在元组。not exists可以表示集合之间的包含关系。
??SQL提供一个布尔函数,用于测试在一个子查询的结果中是否存在重复元组。如果作为参数的子查询结果中没有重复的元组,unique结构将返回true值。
? SQL允许在from子句中使用子查询表达式。在此采用的主要观点是:任何select-from-where表达式返回的结果都是关系,因而可以被插入到另一个select-from-where中任何关系可以出现的位置。
With子句提供定义临时关系的方法,这个定义只对包含with子句的查询有效。
with dept_total (dept_name,value) as
(select dept_name, sum(salary)
from instructor
group by dept_name),
dept_total_avg(value) as
(select avg(value)
from dept_total)
select dept_name
from dept_total,dept_total_avg
where dept_total.value >= dept_total_avg.value
select dept_name, (select count(*)
from instructor
where department.dept_name =instructor.dept_name)
as num_instructors
from department
在数据库中,我们智能删除整个元组,而不能删除某些属性上的值。
? 要往关系中插入数据,我们可以指定待插入的元组,或者写一条查询语句来生成待插入的元组集合。显然,待插入元组的属性值必须在相应属性的域中。同样,待插入元组的分量数也必须是正确的。
??有些情况下,我们可能希望在不改变整个元组的情况下改变其部分属性的值。为达到这一目的, 可以使用update语句。与使用insert ,delete类似,待更新的元组可以用查询语句找到。
个例题
/*关系表:
person(driver_id,name,address)
car(liscense_plate,model,year)
accident(report_number,year,location)
owns(driver_id,liscense_plate)
participated(report_number,liscense_plate,driver_id,damage_amount)*/
/*题目一:找出2017年出过交通事故的人员ID及其发生的事故次数*/
select distinct driver_id as '车主ID' , count(license_plate) as '事故次数'
from participated
where report_number in (select report_number
from accident
where year = 2017)
group by driver_id
having report_number is not null
/*题目二:删除ID为12345的人拥有的年份为2010的所有汽车*/
delete from car
where license_plate = (select license_plate
from owns
where driver_id = '12345')