第三章SQL的数据查询3.3SQL的数据查询查询即检索操作,是对已经存在的基本表及视图进行数据检索,不改变数据本身。3.3.1SELECT语句的基本语法(1):SELECT-FROM-WHERE句型:组成的查询块,一般形式:SELECT列名[{,列名}](指出要检索的数据项)FROM表名[{,表名}](给出要操作的关系表名)WHERE检索条件(给出查询结果应满足的条件)等价于:∏A1,A2,…,An(p(r1r2…rm))(1)、SELECT-FROM-WHERE句型Select语句的含义根据Select子句中的属性列表,对上述结果作投影(π)操作对From子句中的各关系,作笛卡儿积(×)对Where子句中的逻辑表达式进行选择(σ)运算,找出符合条件的元组结果集查询操作的对象是关系,结果还是一个关系,是一个结果集,是一个动态数据集1、SELECT子句说明:对应于关系代数的投影运算,用以列出查询结果集中的期望属性目标列形式:可以为列名,*,算术表达式,聚合函数。(1)、“*”:表示“所有的属性”。示例:检索学生的姓名,年龄和性别SELECTS#,AGE,SEXFROMS;(SELECT*FROMS;)示例:给出所有老师的姓名及税后工资额。selectTNAME,SAL0.95fromTEACHER1、SELECT子句关系定义为:TEACHER(TNO,TNAME,SAL,EDEPT)(2)、select中有含,,,的算术表达式2、from子句说明FROM子句列出查询的对象表。当目标列取自多个表时,在不混淆的情况下可以不用显式指明来自哪个关系,否则,要指出关系名。示例:检索TOM同学所学课程的课程号及成绩selectSNAME,CNO,GRADE,S.SNOfromS,SCwhereS.SNO=SC.SNOandSNAME='TOM'3、WHERE子句说明:查询满足指定条件的元组可以通过WHERE子句实现。WHERE子句常用的查询条件如表所示。常用的查询条件查询条件比较确定范围确定集合自符匹配空值多重条件谓词=,,,=,=,!=,!,NOT+上述比较运算BETWEENANDBETWEENANDIN,NOTINLIKE,NOTLIKEISNULL,ISNOTNULLAND,OR(1)比较示例:查计算机系全体学生的名单•SELECTsnameFROMSWHEREdept='JSJ'3、WHERE子句(1)比较查所有年龄在20岁以下的学生姓名及其年龄SELECTsname,ageFROMSWHEREage20或SELECTsname,ageFROMSWHERENOTage=203、WHERE子句3、WHERE子句•(2)确定范围查询年龄在18至23岁之间的学生的姓名、系别、和年龄SELECTsname,dept,ageFROMSWHEREageBETWEEN18AND23•与BETWEEN...AND...相对的谓词是NOTBETWEEN...AND...是大于还是大于等于?(3)确定集合查物理系(WL)、数学系(XS)和计算机系(JSJ)的学生的姓名和性别SELECTsname,sex,deptFROMSWHEREdeptIN('WL','SX','JSJ')3、WHERE子句与IN相对的谓词是NOTIN,用于查找属性值不属于指定集合的元组。3、WHERE子句(4)多重条件查询逻辑运算符AND和OR可用来联结多个查询条件。如果这两个运算符同时出现在同一个WHERE条件子句中,则AND的优先级高于OR,但用户可以用括号改变优先级。查询的类型1、单表查询2、连接查询3、嵌套查询查询的类型-连接查询在查询中,同时涉及两个或两个以上的表,要根据表中数据的情况作连接。示例:查询学习课程名为‘MATHS’的学生学号和姓名。selects.sno,snamefroms,sc,cwheres.sno=sc.snoandsc.cno=c.cnoandcname='MATHS'查询的类型-嵌套查询在一个select语句的where子句中,又出现了另一个select语句,这种查询称为嵌套查询。子查询中还可以嵌入子查询。示例:检索既学习了C1又学习了C2课程的学生的学号。selectsnofromscwherecno='C1'andsnoin(selectsnofromscwherecno='C2')查询的类型-嵌套查询无论单层嵌套还是多层嵌套查询,执行的过程都是由里向外,即先做最内层的查询,求得一个结果,然后根据这个结果执行上一层查询,由里向外,直到求得最外层的查询结果。考虑:嵌套查询的内层查询执行几次?1、重复元组的处理语法约束:缺省为保留重复元组,也可用关键字all显式指明。若要去掉重复元组,可用关键字distinct或unique指明。示例:找出所有选修了课程的学生。3.3.3SELECT语句中的限定selectdistinctsnofromSC2、条件表达式中的算术比较操作示例:检索课程号为C2且成绩高于85分以上的学生学号和成绩SELECTsno,gradeFROMSCWHEREcno='C2'ANDgrade852、条件表达式中的算术比较操作运算符BETWEEN…AND…可以选择属性列在一定值范围内的行示例检索成绩在70分至80分之间的学生学号,课程号和成绩SELECT*FROMSCWHEREGRADEBETWEEN70AND80;3、列和基本表的改名操作格式old_nameasnew_name为关系和属性重新命名,可出现在select和from子句中。为结果集中的某个属性改名使结果集更具可读性1、属性更名例1:Selectsnoas学号,cnoas课程号,gradeas成绩FromSC例2:Selectsno,sname,2003-ageasbirthdayFromS3、列和基本表的改名操作3、列和基本表的改名操作2.关系更名示例:检索至少选修课程号为C2和C4的学生学号S(SNO,SNAME,AGE,SEX)SC(SNO,CNO,GRADE)C(CNO,CNAME,TEACHER)SELECTX.SNOFROMSCASX,SCASYWHEREX.SNO=Y.SNOANDX.CNO='C2'ANDY.CNO='C4'4、字符串的匹配操作命令格式like:找出满足给定匹配条件的字符串。格式:列名[not]like“字符串”匹配规则:“%”:匹配零个或多个字符。“_”:匹配任意单个字符。escape:定义转义字符,以去掉特殊字符的特定含义,使其被作为普通字符看待。如escape“\”,是定义了\作为转义字符,则可用\%去匹配%,用\_去匹配_,用\\去匹配\。大小写敏感4、字符串的匹配操作示例:列出姓刘的学生的学号、姓名。Selectsno,snameFromStudentWheresnameLIKE‘刘%’SnameSnoSageSsexSdept刘勇9500122男Cs张新9500221女Cs刘晨9500322女If李立9500423男ifSnameSnoSageSsexSdept刘勇9500122男Cs刘晨9500322女If4、字符串的匹配操作示例例:列出张姓且单名的学生的学号、姓名。Selectsno,snameFromSWheresnameLIKE‘张__’4、字符串的匹配操作转义符:escape例:列出课程名称中带有‘_’的课号及课名。Selectcno,cnameFromCWherecnameLIKE‘%\_%’escape‘\’列出名称中含有4个字符以上,且倒数第3个字符是d,倒数第2个字符是_的课程的所有信息。select*fromcwhereCNAMElike“%_d\__”4、字符串的匹配操作查以”DB_”开头,且倒数第三个字符为i的课程的详细情况SELECT*FROMCWHERECnameLIKE’DB\_%i__’ESCAPE’\’;注意这里的匹配字符串’DB\_%i__’。第一个_前面有换码字符\,所以它被转义为普通的_字符。而%、第二个_和第三个_前面均没有换码字符\,所以它们仍作为通配符。其执行结果为:CnoCnameCcredit---------------------------8DB_Design410DB_Programing213DB_DBMSDesign4为了进一步方便用户,增强检索功能,SQL提供了许多聚合函数,主要包括:COUNT([DISTINCT|ALL]*)统计元组个数COUNT([DISTINCT|ALL]列名)统计一列中值的个数SUM([DISTINCT|ALL]列名)计算一列值的总和(此列必须是数值型)AVG([DISTINCT|ALL]列名)计算一列值的平均值(此列必须是数值型)MAX([DISTINCT|ALL]列名)求一列值中的最大值MIN([DISTINCT|ALL]列名)求一列值中的最小值聚合函数聚合函数1、求男学生的总人数和平均年龄SELECTCOUNT(*),AVG(AGE)FROMSWHERESEX='M'聚合函数举例:统计选修了课程的学生人数SELECTCOUNT(DISTINCTS#)FROMSCSELECTcount(grade)as成绩人数,count(*)as总人数,avg(grade)as平均分数fromsc举例:如果有一个grade值为空下面的结果相同吗?1、COUNT(*)对行的计数,不消除重复行2、只有count(*)将空值null,记入结果。示例列出老师的最高、最低、平均工资。selectDNO,max(SAL),min(SAL),avg(SAL)fromTEACHERNull在聚集函数中的角色Count为0其余均忽略NullSum:不将其计入Avg:具有Null的元组不参与Max/Min:不参与举例:SELECTcount(sno),count(sname)froms聚合函数GroupByGROUPBY子句可以将查询结果表的各行按一列或多列取值相等的原则进行分组。对查询结果分组的目的是为了细化集合函数的作用对象。如果未对查询结果分组,集合函数将作用于整个查询结果,即整个查询结果只有一个函数值。如果用GROUP分了组,集合函数将作用于每一个组,即每一组都有一个函数值。聚合函数聚合函数GROUPBY举例:查询各个课程号以及相应的选课人数该SELECT语句对SC表按Cno的取值进行分组,所有具有相同Cno值的元组为一组,然后对每一组作用集函数COUNT以求得该组的学生人数。查询为:SELECTCno,COUNT(Sno)FROMSCGROUPBYCnoSELECTCno,COUNT(Sno)FROMSCGROUPBYCno;结果Having可以针对聚合函数的结果值进行筛选,它是作用于分组计算的结果集跟在GroupBy子句的后面,有GROUPBY才有HAVING聚合函数例:列出选修两门(含)以上课程的学生的学号。SELECTsnoFROMSCGROUPBYsnoHAVINGCOUNT(cno)=2例:列出具有两门(含)以上不及格的学生的学号、不及格的课目数。聚合函数Selectsno,count(cno)FromSCWheregrade60GroupBysnoHavingcount(cno)=2只选出有不及格的学生列出及格的学生的平均成绩。selectSNO,avg(GRADE)fromSCgroupbySNOhavingmin(GRADE)=60聚合函数Having与Where的区别Where决定哪些元组被选择参加运算,作用于关系中的元组Having决定哪些分组符合要求,作用于分组聚合函数的条件关系必须用Having,Where中不应出现聚集函数聚合函数元组显示顺序命令orderby列名[asc|d