SQL基本语句

小虾米原创作品,转载请注明出处:https://www.cnblogs.com/shrimp-can/p/9898735.html

小虾米最近在找工作,笔试题少不了SQL语句,几年没有碰过数据库都忘记了,复习了一下,将常用的简单的SQL语句以例子的形式系统的整理一下。

此文章根据书《数据库系统概念》第三章整理而成。

 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

贯穿整个例子的关系有如下5个,最前面是关系名字,‘:’后面是该关系的属性

1.建筑department:系名dept_name, 建筑building, 预算budget

2.课程course:课程号course_id,课程名称title,课程所属的系名dept_name,学分credits

3.教师信息instructor:教师号ID,教师名字name,教师所在的系dept_name,薪资salary

4.开课信息section:课程号course_id,课程段标识sec_id,学期semester,年份year,课程所在建筑building,课程所在教室号room_number,时间档序号time_slot_id

5.教学信息teaches:教室号ID,课程号course_id,课程信息序号sec_id,学期semester,年份year

6.选课信息takes:学生学号ID,课程标识course_id,课程段标识sec_id,学期semester,年份year,成绩grade

7.学生信息student:学生学号ID,学生姓名name,学生所在系dept_name,总学分tot_cred

 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一、关系的创建与删除create、delete

1.表的创建create table

例1.1:创建一个department关系

create table department

(dept_name varchar(20),

building varchar(15),

budget numeric(12,2),

primary key (dept_name)); //主码

2.表的删除drop table

例1.2:删除关系department

drop table department;

二、单关系简单查询select

1.基本的单关系查询

例2.1:找出所有教师的名字

select name from instructor;

例2.2:找出所有教师所在的系名

select dept_name from instructor;

:因为instructor关系中多个老师可以在一个系中,所以上述查询结果中会有重复的系名

2.去除重复distinct

例2.3:找出所有教师所在的系名,去除重复

select distinct dept_name from instructor;

3.显式指明不去除重复all

例2.4:例2中指明不去除重复

select all dept_name from instructor;

4.算数表达式+、-、*、/运算

例2.5:将教师的薪资增长10%

select ID, name, dept_name, salary*1.1 from instructor;

5.where子句

选出满足特定条件的元组,可以使用逻辑连词and、or 和not。可以使用运算符<、<=、>、>=、=和<>

例2.6:找出所有在Comuter Science系并且工资超过70000美元的教师的姓名

select name from instructor where dept_name='Computer Science' and salary>70000;

 三、多关系简单查询

1.简单查询

例3.1:找出所有教师的姓名,以及他们所在系的名称和系所在建筑的名称

select name, instructor.dept_name, building from instructor, department where instructor.dept_name=department.dept_name;

例3.2:找出Computer Science系的教师名和课程标识

select name, course_id from instructor, teaches where instructor.ID=teaches.ID and dept_name='Computer Science';

2.自然连接natural join

自然连接作用于两个关系,并产生一个关系作为结果,只考虑在关系模式中出现相同属性的取值相同的情况

例3.3:例2可以用自然连接改为

select name, course_id from instructor natural join teaches;

例3.4:列出教师的名字和他们所讲授的课程的名称

select name, title from instructor natural join teaches, course where course.course_id=teaches_course_id;

3.连接中指定哪些列相等join...using

例3.5:例4可以改为

select name, title from (instructor natural join teaches) join course using (course_id);

四、基本运算

1.更名运算as

例4.1:对于所有讲授课程的教师,找出他们的姓名以及所讲授的课程标识,将查找结果的教师名字改为instructor_name

select name as instructor_name, course_id from instructor, teaches where instructor.ID=teaches.ID;

例4.2:将例1中的instructor关系和teaches关系重新命名为T和S

select T.name, S.course_id from instructor as T, teaches as S where T.ID=S.ID

例4.3:找出满足下面条件的所有教师的姓名,他们的工资至少比Biology系某一个教师的工资要高(去除重复的教师姓名)

select distinct T.name from instructor as T, instructor as S where T.salary>S.salary and S.dept_name='Biology';

2.字符串运算

2.1.字符串匹配like %/_

%:匹配任意字符串

_:匹配任意一个字符

Intro%:匹配任意以"Intro"开头的字符串

%Comp%:匹配任意包含"Comp"子串的字符串

_ _ _:匹配只含有三个字符的字符串

_ _ _%:匹配至少含有三个字符的字符串

例4.4:找出所在建筑名称中包含子串‘Watson’的所有系名

select dept_name from department where building like '%Watson%';

2.2.转义字符的处理escape '\'

like 'ab\%cd%' escape '\':匹配所有以'ab%cd'开头的字符串

like 'ab\\cd%' escape '\':匹配所有以ab\cd开头的字符串

3.select中选择所有的属性*

例4.5:找出所有讲授了课程的教师信息

select instructor.* from instructor, teaches where instructor.ID=teaches.ID;

4.排列查询结果中元组的显示次序order by

order by默认升序,desc表示降序,asc表示升序

例4.6:按字母顺序列出Physics系的所有教师名字

select name from instructor where dept_name='Physics' order by name;

例4.7:按salary的降序列出整个instrutor关系,如果几位教师的工资相同,就按他们的名字升序排列

select * from instructor order by salary desc, name asc;

5.where子句的谓词between... and...

例4.8:找出工资在90000美元和100000美元之间的教师的姓名

select name from instructor where salary between 90000 and 100000;

它与此SQL语句等价

select name from instructor where salary>=90000 and salary<=100000;

例4.9:查找Biology系讲授了课程的所有教师的姓名和他们所讲授的课程标识

select name, course_id from instructor and teaches where (instructor.ID, dept_name)=(teaches.ID, 'Biology');

它与下面的SQL语句等价

select name, course_id from instructor and teaches where instructor.ID=teaches.ID and dept_name='Biology';

五、集合运算

1.并运算union

union会自动去除重复,要想保留所有的重复信息,用union all替代union

例5.1:找出在2009年秋季开课或者在2010年春季开课或者两个学期都开课的所有课程标识

(select course_id from section where year=2009 and semester='Fall') union 

(select course_id from section where year=2010 and semester='Spring');

2.交运算intersect

intersect也会自动去除重复,要想保留所有的重复,用intersect all替代intersect

例5.2:找出在2009年秋季和2010年春季同时开课的所有课程序号的集合

(select course_id from section where year=2009 and semester='Fall') intersect 

(select course_id from section where year=2010 and semester='Spring');

3.差运算except

将会在第一个关系中减去所有在关系2中出现的元祖,最后的结果将不会有重复的元组出现。如果想保留重复,用except all替代except

例5.3:找出在2009年秋季开课但不在2010年春季开课的所有课程序号

(select course_id from section where year=2009 and semester='Fall') except

(select course_id from section where year=2010 and semester='Spring');

六、聚集函数

1.基本聚集

平均值:avg

最小值:min

最大值:max

总和:sum

计数:count

例6.1:找出Computer Science系教师的平均工资

select avy(salary) from instructor where dept_name='Comouter Science';

例6.2:例1中给平均工资赋个新名称avg_salary

select avy(salary) as avg_salary from instructor where dept_name='Comouter Science';

例6.3:找出在2010年春季学期讲授课程的教师总数

select count (distinct ID) from teaches where semester='Spring' and year=2010;

注意:一个教师可能讲授几个课程段,但是在这里只应被计算一次,因此需要去除重复

例6.4:计算课程信息关系中的元祖个数

select count (*) from course;

2.分组聚集group by

group by将在该属性取值相同的元组划分为一组

例6.5:找出每个系的平均工资

select avy(salary) from instructor group by dept_name;

例6.6:找出每个系在2010年春季讲授了课程的教师人数

select dept_name, count(distinct ID) from teaches natural join instructor  where semester='Spring' and year=2010 group by dept_name;

3.having子句

对group by子句构成的分组限定条件

例6.7:找出教师平均工资超过42000美元的系

select dept_name, avg(salary) as avg_salary from instructor group by dept_name having avg(salary)>42000;

例6.8:对于在2009年讲授的每个课程段,如果该课程段有至少2名学生选课,找出选修该课程段的所有学生的总学分的平均值

select course_id, year, semester, sec_id, avg(tot_cred) from takes natural join student group by course_id, sec_id, semester, year having count(ID)>=2;

七、嵌套子查询

1.集合成员的资格in, not in

例7.1:找出在2009年秋季开课,同时也在2010年春季开课的所有课程

select distinct course_id from section where semester='Fall' and year=2009 and course_id in

(select course_id from section where semester='Spring' and year=2010);

例7.2:找出在2009年秋季开课,但是不在2010年春季开课的所有课程

select distinct course_id from section where semester='Fall' and year=2009 and course_id not in

(select course_id from section where semester='Spring' and year=2010);

 例7.3:查找既不叫‘Mpzart’也不叫'Einstein'的教师姓名

select distinct name from instructor where name not in ('Mozart', 'Einstein');

例7.4:找出不同的学生总数,他们选修了ID为10101的教师所讲授的课程

select count(sidtinct ID) from takes where course_id, sec_id, semester, year in (select course_id, sec_id, semester, year from teaches where teaches.ID=10101);

2.集合的比较

至少比某一个要大:>some

此外还有:<some,<=some,>=some,=some(等价于in),<>some

比所有的都大:>all

此外还有:<all,<=all,>=all,=all,<>all(等价于not in)

例7.5:找出满足下面条件的所有教师的姓名,他们的工资至少比Biology系某一个教师的工资要高

select name from instructor where salary >some (select salary from instructor where dept_name='Biology');

例7.6:找出满足下面条件的所有教师的姓名,他们的工资比Biology系每个教师的工资都高

select name from instructor where salary >all (select salary from instructor where dept_name='Biology');

例7.7:找出平均工资最高的系

select dept_name from instructor where avg(salary) >=all (select avg(salary) from instructor group by dept_name);

3.空关系测试exists, not exists

关系A包含关系B写成 not exists (B except A)

例7.8.找出在2009年秋季学期和2010年春季学期同时开课的所有课程标识

select course_id from section as S where year=2009 and semester='Fall' and exists

(select * from section as T where year=2010 and semester='Spring' and S.course_id=T.course_id);

例7.9:找出选修了Biology系开设的所有课程的学生

select S.ID, S.name from student as S where not exists ((select course_id from course where dept_name='Biology') except (select T.course_id from takes as T where S.ID=T.ID));

4.重复元组存在性测试unique, not unique

例7.10:找出所有在2009年最多开设一次的课程

select T.course_id from course as T where unique (select R.course_id from section as R where T.course_id=R.course_id and R.year=2009);

或者

select T.course_id from course as T where 1 >= (select count(R.course_id) from section as R where T.course_id=R.course_id and R.year=2009);

例7.11:找出所有在2009年最少开设两次的课程

select T.course_id from course as T where not unique (select R.course_id from section as R where T.course_id=R.course_id and R.year=2009);

5.from子句中的子查询

例7.12:找出系平均工资超过42000美元的那些系中教师的平均工资

select dept_name, avg_salary from (select dept_name, avg(salary) as avg_salary from instructor group by dept_name) where avg_salary > 42000;

例7.13:可以给from子句中的查询结果关系进行命名,并对其属性进行命名

select dept_name, avg_salary from (select dept_name, avg(salary) from instructor group by dept_name) as dept_avg (dept_name, avg_salary) where avg_salary > 42000;

例7.14:找出所有系中工资总额最大的系

select dept_name, max(tot_salary) from (select dept_name, sum(salary) from instructor group by dept_name) as dept_total (dept_name, tot_salary);

6.with子句

 with子句提供定义临时关系的方法

例7.15:找出具有最大预算值的系

with max_budget (value) as (select max(budget) from department)

select budget from department, max_budget where departmen.budget=max_budget.value;

例7.16:查找所有工资总额大于所有系平均工资总额的系

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;

7.标量子查询

子查询出现在返回单个值的表达式能够出现的任何地方。

例7.17:列出所有的系和他们拥有的教师数

select dept_name, (select count(*) from instructor where department.dept_name=instructor.dept_name) as num_instructors from department;

八、数据库的修改

1.删除delete

删除整个关系前面我们已经讲了,用drop table,这里是删除关系中的元组

例8.1:从instructor关系中删除与Finance系教师相关的所有元组

delete from instructor where dept_name='Finance';

例8.2:删除所有工资在13000美元到15000美元之间的教师

delete from instructor where salary between 13000 and 15000;

例8.3:从instructor关系中删除所有这样的教师元组,他们在位于Watson大楼的系工作

delete from instructor where dept_name in (select dept_name from department where building='Watson');

例8.4:删除工资低于大学平均工资的教师记录

delete from instructor where salary < (select avg(salary) from instructor);

2.插入insert into

例8.5:插入的信息是Comouter Science系开设的名为'Database System'的课程CS-437,它有4个学分

insert into course values('CS-437', 'Database System', 'Computer Science', 4);

例8.6:例5中指定属性插入

insert into course (course_id, title, dept_name, credits) values('CS-437', 'Database System', 'Computer Science', 4);

例8.7:我们想让Music系每个修满144学分的学生成为Music系的教师,其工资为18000美元

insert into instructor select ID, name, dept_name, 18000 from student where dept_name='Music' and tot_cred>=144;

3.更新update

例8.8:将所有教师的工资增长5%

update instructor set salary=salary*1.05;

例8.9:给工资低于70000美元的教师工资增长5%

update instructor set salary=salary*1.05 where salary<70000;

例8.10:对工资低于平均数的教师涨5%的工资

update instructor set salary=salary*1.05 where salary<(select avg(salary) from instructor);

例8.11:给工资超过100000美元的教师涨3%的工资,其余教师涨5%

update instructor set salary=salary*1.03 where salary>100000;

update instructor set salary=salary*1.05 where salary<=100000;

例8.12:将例11用case结构

update instructor

set salary = case

                    when salary <=100000 then salary*1.05

                    else salary*1.03

          end

例8.13:把每个student元组的tot_cred属性值设为该学生成功学完的课程学分的总和;假设学生在某门课程上的成绩既不是'F'也不是空,那么他成功学完了这门课程

update student set tot_cred = (select sum(credits) from takes natural join course where student.ID=takes.ID and takes.grade <>'F' and takes.grade is not null);

 

posted @ 2018-11-03 21:32  shrimp_929  阅读(3030)  评论(0编辑  收藏  举报