数据库:关系数据库标准语言(二)

一章写不完啊,这里全是概念和实战,所以再来一章,希望这章可以学的好一点


掌握连接查询

连接查询

连接查询:同时涉及多个表的查询。用来连接两个表的条件称为连接条件或连接谓词 。
连接条件的一般格式

[<表名1>]<列名1> <比较运算符> [<表名2>]<列名2>
或 [<表名1>]<列名1> BETWEEN [<表名2>]<列名2> AND [<表名2>]<列名3>

其中:连接谓词中的列名称为连接字段,连接条件中的各连接字段类型必须是可比的,但不必是相同的。

嵌套循环法
首先在表1中找到第一个元组,然后从头开始扫描表2,逐一查找满足连接件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。
表2全部查找完后,再找表1中第二个元组,然后再从头开始扫描表2,逐一查找满足连接条件的元组,找到后就将表1中的第二个元组与该元组拼接起来,形成结果表中一个元组。
重复上述操作,直到表1中的全部元组都处理完毕 。

排序合并法
首先按连接属性对表1和表2排序。
对表1的第一个元组,从头开始扫描表2,顺序查找满足连接条件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。当遇到表2中第一条大于表1连接字段值的元组时,对表2的查询不再继续。
找到表1的第二条元组,然后从刚才的中断点处继续顺序扫描表2,查找满足连接条件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。直接遇到表2中大于表1连接字段值的元组时,对表2的查询不再继续。
重复上述操作,直到表1或表2中的全部元组都处理完毕为止 。

索引连接
对表2按连接字段建立索引。
对表1中的每个元组,依次根据其连接字段值查询表2的索引,从中找到满足条件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。

SQL中连接查询的主要类型广义笛卡尔积查询等值连接(含自然连接)查询非等值连接查询自身连接查询外连接查询复合条件连接查询

广义笛卡尔积(很少使用):不带连接谓词的连接。

SELECT  Student.* ,  SC.*  FROM  SStudent, SC;

等值连接:连接运算符为 = 的连接操作。

格式:[<表名1>.]<列名1> = [<表名2>.]<列名2>
说明:任何子句中引用表1和表2中同名属性时,都必须加表名前缀。引用唯一属性名时可以加也可以省略表名前缀。

查询每个学生及其选修课程的情况

SELECT  SStudent.*,SC.*  FROM  SStudent,SC
WHERE  SStudent.Sno = SC.Sno;

自然连接:等值连接的一种特殊情况,把目标列中重复的属性列去掉。

查询每个学生及其选修课程的情况

SELECT  SStudent.Sno,Sname,Ssex,Sage, Sdept,Cno,Grade
FROM SStudent,SC  WHERE  sStudent.Sno = SC.Sno;

非等值连接查询:连接运算符不是 = 的连接操作。

自身连接:一个表与其自己进行连接。连接需给表起别名以示区别,由于所有属性名都是同名属性,因此须使用别名前缀。

查询每一门课的间接先修课(即先修课的先修课)。

SELECT  FIRST.Cno,SECOND.Cpno  
FROM  SCourse  FIRST,SCourse  SECOND 
WHERE FIRST.Cpno = SECOND.Cno;

外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN)、右外连接(RIGHT OUTER JOIN或RIGHT JOIN) 和全外连接(FULL OUTER JOIN或FULL JOIN)三种。与内连接不同的是,外连接不只列出与连接条件相匹 配的行,而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行

复合条件连接:WHERE子句中含多个连接条件

查询选修2号课程且成绩在90分以上所有学生的学号、姓名。

SELECT Student.Sno, student.Sname FROM  Student, SC
WHERE Student.Sno = SC.Sno AND SC.Cno= ' 2 ' AND  SC.Grade > 90

查询每个学生的学号、姓名、选修的课程名及成绩。

SELECT SStudent.Sno,Sname,Cname,Grade
   FROM    SStudent,SC,SCourse
   WHERE SStudent.Sno = SC.Sno  and SC.Cno = SCourse.Cno;

嵌套查询

概述:一个SELECT-FROM-WHERE语句称为一个查询块,将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询。其中外层查询块称为父查询,内层查询块称为子查询,子查询不能使用ORDER BY子句。层层嵌套方式反映了 SQL语言的结构化,有些嵌套查询可以用连接运算来替代。

    SELECT Sname	 FROM Student 	外层查询/父查询
    WHERE Sno INSELECT Sno FROM SC             内层查询/子查询
             WHERE Cno= ' 2 ');     

嵌套查询分类
不相关子查询:子查询的查询条件不依赖于父查询,由里向外逐层处理。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件。
相关子查询:子查询的查询条件依赖于父查询,首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表;然后再取外层表的下一个元组。重复这一过程,直至外层表全部检查完为止。
引出子查询的谓词:带有IN谓词的子查询、带有比较运算符的子查询、带有ANY或ALL谓词的子查询、带有EXISTS谓词的子查询。

带有IN谓词的子查询

  • 查询与刘晨在同一个系学习的学生。### 集合查询
  • 确定刘晨所在系名。
    SELECT Sdept FROM Student WHERE Sname= ‘ 刘晨 ’;
  • 查找所有在IS系学习的学生。
    SELECT Sno,Sname,Sdept FROM Student WHERE Sdept= ’ IS ';
  • 上例可构造嵌套查询:将第一步查询嵌入到第二步查询条件中。 SELECT Sno,Sname,Sdept FROM SStudent WHERE Sdept IN
    (SELECT Sdept FROM SStudent WHERE Sname=‘刘晨’);
  • 此查询为不相关子查询,DBMS求解该查询时也是分步去做的。
    也可用自身连接完成本查询要求:
    SELECT S1.Sno,S1.Sname,S1.Sdept FROM SStudent S1,SStudent S2
    WHERE S1.Sdept = S2.Sdept AND S2.Sname =‘刘晨’;
  • 父查询和子查询中的表均可以定义别名:
    SELECT Sno,Sname,Sdept FROM SStudent S1 WHERE S1.Sdept IN
    (SELECT Sdept FROM SStudent S2 WHERE S2.Sname= ‘刘晨’);

带有比较运算符的子查询:当能确切知道内层查询返回单值时,可用比较运算符(>,<,=,>=,<=,!=或< >)。

  • 假设一个学生只可能在一个系学习,并且必须属于一个系,则可以用 = 代替IN :
SELECT Sno,Sname,Sdept     FROM    Student  WHERE Sdept=
    SELECT Sdept  FROM Student WHERE Sname=‘ 刘晨 ’;
  • 子查询一定要跟在比较符之后,一个错误的例子如下:
     SELECT  Sno,Sname,Sdept     FROM     Student
     WHERE ( SELECT Sdept   FROM Student
                       WHERE Sname= ‘ 刘晨 ’ )     = Sdept;

带有ANY或ALL谓词的子查询:谓词ANY表示任意一个值,ALL表示所有值,但需要配合使用比较运算符。

(>=) ANY 大于(大于等于)子查询结果中的某个值
(>= )ALL 大于(大于等于)子查询结果中的所有值
< (<= ) ANY 小于(小于等于)子查询结果中的某个值
< (<= ) ALL 小于(小于等于)子查询结果中的所有值
= ANY 等于子查询结果中的某个值
=ALL 等于子查询结果中的所有值(通常没有实际意义)
!=ANY 不等于子查询结果中的某个值
!=ALL 不等于子查询结果中的任何一个值

查询其他系中比信息系任意一个(其中某一个)学生年龄小的学生姓名和年龄。

    SELECT Sname,Sage    FROM    SStudent
    WHERE Sage < ANY (SELECT  Sage  FROM    SStudent
                                  WHERE Sdept='IS')  
                            AND Sdept <>'IS';    

/* 注意这是父查询块中的条件 */
结果: Sname Sage
王敏 18
执行过程:
1.DBMS执行此查询时,首先处理子查询,找出 IS系中所有学生的年龄,构成一个集合(19,18)。
2. 处理父查询,找所有不是IS系且年龄小于19 或 18的学生。
用集函数实现子查询通常比直接用ANY或ALL查询效率要高,
因为前者通常能够减少比较次数。
用集函数实现例39如下:
SELECT Sname,Sage FROM Student
WHERE Sage < (SELECT MAX(Sage) FROM Student
WHERE Sdept= ’ IS ') AND Sdept <> ’ IS ’;
查询其他系中比IS系所有学生年龄都小的学生姓名及年龄。

用ALL谓词

    SELECT Sname,Sage  FROM Student WHERE Sage < ALL
    (SELECT Sage  FROM Student   WHERE Sdept= ' IS ')
    AND Sdept <> ' IS ’;

用集函数

     SELECT Sname,Sage   FROM Student   WHERE Sage < 
     (SELECT MIN(Sage)  FROM Student  WHERE Sdept= ' IS ')
     AND Sdept <>' IS ’;

带有EXISTS谓词的子查询
[NOT]EXISTS谓词:相当于存在量词 。带有EXISTS谓词的子查询不返回任何数据,只产生逻辑true或false,若内层查询结果非空则返回真值,否则返回假值。由EXISTS引出的子查询的目标列表达式通常都用* ,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义。

掌握集合查询

集合查询:标准SQL直接支持并操作,而一般商用数据库支持并操作、交操作和差操作。
并操作(UNION):参加UNION操作的各结果表的列数必须相同;对应项的数据类型也必须相同。一般格式为:
<查询块>
UNION
<查询块>

查询计算机系的学生及年龄不大于19岁的学生。

SELECT *  FROM Student  WHERE Sdept= 'CS'
				UNION
               SELECT *  FROM Student   WHERE Sage<=19
SELECT  DISTINCT  *  FROM Student   
               WHERE Sdept= 'CS'  OR  Sage<=19

查询选修了课程1或者选修了课程2的学生。

        SELECT Sno   FROM SC  WHERE Cno=' 1 '
        UNION
        SELECT Sno   FROM SC  WHERE Cno= ' 2 '
       SELECT  DISTINCT  Sno   FROM SC
        WHERE Cno=' 1 '  OR  Cno= ' 2 '

设数据库中有一教师表Teacher(Tno, Tname,…)。查询学校中所有师生的姓名。

SELECT Sname   FROM   Student
        UNION
        SELECT  Tname   FROM   Teacher;

交操作(INTERSECT):标准SQL中没有提供集合交操作,但可用其他方法间接实现。

查询计算机系的学生与年龄不大于19岁的学生的交集(实际上就是查询计算机系中年龄不大于19岁的学生)。

SELECT *  FROM Student  WHERE Sdept= 'CS' AND  Sage<=19

查询选修课程1的学生集合与选修课程2的学生集合的交集(实际上就是查询既选修了课程1又选修了课程2的学生)。

     SELECT Sno  FROM SC  WHERE Cno=' 1 ' AND Sno IN
      (SELECT Sno  FROM SC  WHERE Cno=' 2 ')

差操作(MINUS):标准SQL中没有提供集合差操作,但可用其他方法间接实现。

查询计算机科学系的学生与年龄不大于19岁的学生的差集(实际上就是查询计算机科学系中年龄大于19岁的学生)。

SELECT * FROM Student  WHERE Sdept= 'CS' AND  Sage>19

对集合操作结果的排序: ORDER BY子句用数字指定排序属性,只用于对最终查询结果排序,不能对中间结果排序。任何情况下,ORDER BY子句只能出现在最后。
错误写法:

SELECT  *  FROM  Student  WHERE Sdept= 'CS'  ORDER BY Sno
       UNION
SELECT *  FROM  Student  WHERE Sage<=19  ORDER BY Sno;

正确写法:

SELECT *  FROM Student  WHERE Sdept= 'CS'
       UNION
SELECT *  FROM Student  WHERE Sage<=19  ORDER BY 1

理解SELECT语句的一般格式

查询年龄最大的三个学生的姓名、年龄及所在的系

Select TOP 3 sname,sdept from student order by sage desc

如果包括并列的第三名的学生。则为。

Select TOP 3 with ties sname,sdept from student order by sage desc

用了with ties 需要order by
不用order得到的结果可能与希望的不同。

查询VB课程考试成绩前三名的学生的姓名和成绩

Select TOP 3 with ties sname,grade from student s join sc on s.sno=sc.sno join course c on c.cno=sc.cno where cname=‘VB’ order by grade DESC

语法格式:
Select 查询表序列 into 新表名
from 数据源 where [<条件>]……
新表有二类:1)永久的表,起一个表名就可以了;
2)局部临时表:表名前加#,当前连接可用,生存期为当前连接的生存期.
全局临时表:表名前加##,所有连接都可用.生存期为当前连接的生存期

将计算机系的学生信息存入#computer局部临时表中。

 select sno,sname,ssex,sage into #computer from student where sdept=‘计算机系’

将修了VB课程的学生的学号及成绩存入全局临时表##VB中

Select sno,grade into ##VB from sc join course c on c.cno=sc.cno where cname=‘VB’

将计算机系学生的姓名、修课的课程名和成绩存入永久表S_C_G中

Select sname,cname,grade into S_C_G from student s join sc on s.sno=sc.sno join course on c.cno=sc.cno where sdept=‘计算机系’

在已经存在的表中插入数据

insert into sc1 select * from sc;

查询001号课程的学号和成绩,并进行如下处理成绩>90 显示优。80-89:良

Select sno,
  CASE
    WHEN GRADE>=90 THEN ‘优’
WHEN GRADE BETWEEN 80 AND 89 THEN ‘良’
WHEN GRADE BETWEEN 70 AND 79 THEN ‘中’
WHEN GRADE BETWEEN 60 AND 69 THEN ‘及格’
WHEN GRADE<60 THEN ‘不及格’
End as degree 
From sc 
Where cno=001and grade is not null
Select 
  CASE
    WHEN degree>=90 THEN '优'
WHEN degree BETWEEN 80 AND 89 THEN '优'
WHEN degree BETWEEN 70 AND 79 THEN '良'
WHEN degree BETWEEN 60 AND 69 THEN '及格'
WHEN degree<60 THEN '不及格'
  End as grade
  From score
Where degree is not null group by degree
Use pubs;
Select category=
 case type
      when 'popular_comp' then '流行计算类'
when 'mod_cook' then '现代烹饪类'
when 'business' then '商业类'
when 'psychology' then '心理学类'
when 'trad_cook' then '传统烹饪类'
Else '未分类'
End,
Title,price from titles where price is not null order by type,price
SELECT语句的一般格式
  SELECT [ALL|DISTINCT] <目标列表达式> [别名] [,<目标列表达式> [别名]]FROM  <表名或视图名> [别名]  [ ,<表名或视图名> [别名]][WHERE <条件表达式>]
  [GROUP BY <列名1>[,<列名1>] ...
  [HAVING <条件表达式>]]
  [ORDER BY <列名2>[ASC|DESC] [,<列名2> [ASC|DESC]] ]

猜你喜欢

转载自blog.csdn.net/weixin_62529383/article/details/129993467