错误的写法 SELECT DISTINCT Cno,DISTINCT Grade FROM SC; 正确的写法 SELECT DISTINCT Cno,Grade FROM SC; 二。空值查询:“IS NULL” 不能用 “= NULL” 取代
三。利用GROUP BY子句分组查询
◼ 细化聚集函数的作用对象 ◼ 未对查询效果分组,聚集函数将作用于整个查询效果 ◼ 对查询效果分组后,聚集函数将分别作用于每个组 ◼ 分组方法 ◼ 按指定的一列或多列值分组,值相等的为一组 ◼ 利用GROUP BY子句后,SELECT子句的列名列 表中只能出现分组属性和聚集函数 ◼ GROUP BY子句的作用对象是查询的中间效果表【例】求各个课程号及相应的选课人数。 SELECT Cno,COUNT(*) --COUNT(Sno) FROM SC GROUP BY Cno; 【例】查询选修了3门以上课程的门生学号 SELECT Sno FROM SC GROUP BY Sno HAVING COUNT(*) >3;查询有3门以上课程是90分以上的门生的学 号及(90分以上的)课程数 SELECT Sno, COUNT(*) FROM SC WHERE Grade>=90 GROUP BY Sno HAVING COUNT(*)>=3; 四。where与having的区别
WHERE 子句允许你指定过滤条件,这些条件基于表中的单个行。你不能在 WHERE 子句中利用聚合函数(如 SUM(), AVG(), COUNT(), 等)来过滤分组。
GROUP BY 子句通常与聚合函数一起利用,以盘算每个组的汇总值。你不能在 GROUP BY 子句中指定单个行的条件,但可以在 HAVING 子句中如许做,HAVING 子句允许你基于聚合函数的效果来过滤分组。
五。毗连查询
毗连条件中各毗连字段的类型必须是可比的,但不必是 相同的
六。嵌套查询(又称子查询)
子查询的限制 ◼ 不能利用ORDER BY子句 嵌套查询的分类与求解方法 ◼ 不相关子查询 ◼ 子查询的查询条件不依靠于父查询 ◼ 由里向外逐层处置惩罚。每个子查询在上一级查询处置惩罚之前 求解,子查询的效果用于建立其父查询的查找条件。 ◼ 相关子查询 ◼ 子查询的查询条件依靠于父查询 ◼ 先取外层查询中表的第一个元组,根据它与内层查询相 关的属性值处置惩罚内层查询,若WHERE子句返回值为真, 则取此元组放入效果表;然后再取外层表的下一个元组; 重复这一过程,直至外层表全部检查完为止【例】找出每个门生所选修课程结果超过该门课 程平均结果的课程号。 SELECT Sno, Cno /*外层查询/父查询*/ FROM SC x WHERE Grade >=(SELECT AVG(Grade) FROM SC y WHERE y.Cno=x.Cno); /*内层查询/子查询*/子查询不能在比较符之前 ◼ 错误的例子 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查询效 率要高,由于前者通常可以或许减少比较次数。 【例】查询其他系中比CS系任意一个门生年龄小的 门生姓名和年龄 ◼ 用ANY谓词实现 SELECT Sname, Sage FROM Student WHERE Sage < ANY ( SELECT Sage FROM Student WHERE Sdept= 'CS') AND Sdept <> 'CS' ; ◼ 用聚集函数实现 SELECT Sname, Sage FROM Student WHERE Sage < ( SELECT MAX(Sage) FROM Student WHERE Sdept= 'CS') AND Sdept <> 'CS' ;带有EXISTS谓词的子查询 ◼ 带有EXISTS谓词的子查询不返回任何数据,只产生逻 辑真值“true”或逻辑假值“false”。 ◼ 若内层查询效果非空,则返回真值 ◼ 若内层查询效果为空,则返回假值 ◼ 由EXISTS引出的子查询,其目标列表达式通常用* ,因 为带EXISTS的子查询只返回真值或假值,给出列名无 实际意义【例】查询全部选修了1号课程的门生姓名。 ◼ 思路分析:在 Student 中依次取每个元组的 Sno值,用此 值去检查 SC 关系;若 SC 中存在如许的元组,其 Sno 值 即是此 Student.Sno 值,且Cno= ‘1’ ,则取此 Student.Sname 送入效果关系用嵌套查询 SELECT Sname FROM Student WHERE EXISTS (SELECT * FROM SC WHERE Sno=Student.Sno AND Cno= ' 1 '); ◼ 全部带IN谓词、比较运算符、ANY和ALL谓词的子查询 都能用带EXISTS谓词的子查询等价更换。 ◼ 带有EXISTS谓词的相关子查询只关心内层查询是否有 返回值,不必要查具体值,效率不低于相关子查询。 用EXISTS/NOT EXISTS实现全称量词 ◼ SQL语言中没有全称量词 任取(For all) ◼ 可以把带有全称量词的谓词转换为等价的带有存在量词 的谓词: (任取x)P ≡ 非(存在x(非P)) 【例】查询选修了全部课程的门生姓名。SELECT Sname FROM Student WHERE NOT EXISTS #如许的课不存在(SELECT * FROM Course WHERE NOT EXISTS #这门课他没选(SELECT * FROM SC WHERE Sno= Student.Sno AND Cno= Course.Cno)); 用EXISTS/NOT EXISTS实现逻辑蕴函 ◼ SQL语言中没有蕴函(Implication)逻辑运算【例】查询至少选修了门生95001选修的全部课程的 门生的学号解题思路: ◼ 用逻辑蕴函表达:查询学号为x的门生,对全部的课程y, 只要95001门生选修了课程y,则x也选修了y ◼ 变换后语义:对于门生x,不存在如许的课程y,门生 95001选修了y,而门生x没有选。SELECT DISTINCT Sno FROM SC SCX WHERE NOT EXISTS (SELECT * FROM SC SCY WHERE SCY.Sno = '95001' AND NOT EXISTS (SELECT * FROM SC SCZ WHERE SCZ.Sno=SCX.Sno AND SCZ.Cno=SCY.Cno));#一个表涉及多次查询时最好起别名,而且as是可以省略的七。集合查询
并操纵 ◼ 语法形式 <查询块> UNION [ALL] <查询块>; ◼ 两个查询效果的属性列个数相同,对应项的数据 类型必须可以或许通过隐式转换相互兼容。 ◼ 利用UNION归并多个效果集时,系统会自动去掉 重复元组。 ◼ 利用UNION ALL操纵符,可以保留重复元组UNION效果会合的列名与UNION运算中第一个 SELECT语句的效果会合的列名相同, 其他的SELECT语句的效果集列名将被忽略。 差操纵 ◼ 标准SQL中没有提供集合差操纵,但可用其他方 法间接实现。 【例】查询门生姓名与西席姓名的差集。实际上是 查询学校中未与西席同名的门生姓名。 SELECT DISTINCT Sname FROM Student WHERE Sname NOT IN (SELECT Tname FROM Teacher); #另一种方式SELECT Sname FROM Student EXCEPT SELECT Tname FROM Teacher;对集合操纵效果的排序 ◼ 在实行集合操纵时,默认按照末了效果表中第一 列数据的升序方式排列记载。 ◼ 各SELECT子句不能含有ORDER BY子句,但是可 以将ORDER BY子句放在末了的SELECT语句后面, 以便对末了的效果表排序。 ◼ ORDER BY子句只能用于对终极查询效果排序, 不能对中间效果排序。 ◼ 任何情况下,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;基于派生表的查询 ◼ 子查询出现在FROM子句中,这时子查询天生的 临时派生表(Derived Table)成为主查询的查询 对象 【例】找出每个门生超过他自己选修课程平均结果 的课程号。 SELECT Sno, Cno FROM SC, (SELECT Sno, Avg(Grade) avg_grade FROM SC GROUP BY Sno) AS Avg_sc WHERE SC.Sno = Avg_sc.Sno and SC.Grade >=Avg_sc.avg_grade;
视图
一。创建视图
◼ 语句格式 CREATE VIEW <视图名> [(<列名1> [,<列名2>]…)] AS < SELECT语句> [WITH CHECK OPTION]; ◼ DBMS实行CREATE VIEW语句时只是把视图的 定义存入数据字典,并不实行此中的SELECT语句。 在对视图举行操纵时才按照视图定义天生数据, 供用户利用。 ◼ SELECT语句表示子查询,视图的属性列和数据 都是由该子查询决定的。 ◼ 选项[(<列名1>[, <列名2>])]用来定义视图的 列名。 ◼ 组成视图的属性列名可以全部省略或全部指定 ◼ 省略: 由SELECT查询效果的目标列名组成 ◼ 以下情况必须明确指定视图的全部列名: (1) 目标列中包罗聚集函数或表达式 (2) 视图中包罗出现在多个表中的相同列名 (3) 必要在视图中为某个列启用新的更合适的名字 ◼ 建立带表达式的视图 【例】按系建立门生平均年龄的视图。 CREATE VIEW D-Sage (Sdept, Avgage) AS SELECT Sdept, AVG(Sage) FROM Student GROUP BY Sdept; ◼ 因在SELECT目标表中有聚集函数AVG,视图定义中必 须含有列名选项。 ◼ 视图的列名与SELECT后的列名相对应,即使有与基本 表相同的列名也不能省略。 ◼ 建立基于多个基表的视图 【例】建立盘算机系选修了C2课的门生姓名和结果 的视图。 CREATE VIEW CS_SC(Sno, Sname, Grade) AS SELECT Student.Sno, Sname, Grade FROM Student, SC WHERE Sdept='盘算机' AND Student.Sno=SC.Sno AND SC.Cno='C2'; 以 SELECT * 方式创建的视图可扩充性差,应尽可能制止. 二。 DBMS实现视图查询的方法
◼ 实体化视图(View Materialization) 1. 有效性检查:检查所查询的视图是否存在 2. 实行视图定义,将视图临时实体化,天生临 时表 3. 查询视图转换为查询临时表 4. 查询完毕删除被实体化的视图(临时表) ◼ 视图消解法(View Resolution) 1. 举行有效性检查,检查查询的表、视图等是 否存在;假如存在,则从数据字典中取出视 图的定义; 2. 把视图定义中的子查询与用户的查询联合起 来,转换成等价的对基本表的查询; 3. 实行修正后的查询。【例】查询专业系,要修业生平均年龄小于21岁。 CREATE VIEW D-Sage (Sdept, Avgage) AS SELECT Sdept, AVG(Sage) FROM Student GROUP BY Sdept; SELECT Sdept FROM D-Sage WHERE Avgage<21; SELECT Sdept FROM Student GROUP BY Sdept HAVING AVG(Sage)<21; 转化为 对基本表的查询 ◼ 视图消解法的局限性 ◼ 有些情况下,视图消解法不能天生正确查询。 ◼ 接纳视图消解法的DBMS会限制这类查询。 ◼ 对于简朴视图,视图消解是总能举行的。 ◼ 实体化视图的方法 ◼ 无限制 三。视图更新
1,若视图的字段来自聚集函数或含有GROUP BY子句、含有DISTINCT短语,则此视图不允许更新 【例】通过视图D-Sage插入盘算机系门生的平均 年龄('盘算机' ,21)。 INSERT INTO D-Sage VALUES ('盘算机',21); 以上插入语句无法实行,由于视图D-Sage为不可 更新视图。 CREATE VIEW D-Sage (Sdept, Avgage) AS SELECT Sdept, AVG(Sage) FROM Student GROUP BY Sdept; 2,若视图由两个以上基本表导出不允许更新 【例】通过视图CS_SC 删除门生刘豁亮的信息。 DELETE FROM CS_SC WHERE Sname='刘豁亮'; 以上语句无法实行,由于不能转化为对基本表的操纵, 删除操纵的语义不明确。 CREATE VIEW CS_SC(Sno, Sname, Grade) AS SELECT Student.Sno, Sname, Grade FROM Student, SC WHERE Sdept='盘算机' AND Student.Sno=SC.Sno AND SC.Cno='C2'; 3,若视图定义中有嵌套查询,而且内层查询的FROM子句中涉及的表也是导出该视图的基本表,则此视图不允许更新。
注:
◼ 仅在一个表上取其行列值且其列中包罗了候选键, 如许所形成的视图都是可更新的,这类视图称为 “行列子集视图” 。 ◼ 除行列子集视图外的视图的更新都会受到限制 约束