• 数据库之数据查询


    数据库是以select语句为基本对数据库进行信息查询的,这里面有很多使用方式,下面对此做一一总结。数据库查询语句的一般格式为:

    select [all | distinct]<目标列表达式>[,<目标列表达式>]---

    from <表名或视图名>[,<表名或视图名>]---

    [where <条件表达式>]

    [group by <列名1>[having <条件表达式>]]

    [order by <列名2>[ASC|DESC]];

    其中,如果有group by子句,则将结果按<列名1>的值进行分组,该属性列值相等的元祖为一个组。通常会在每组中使用聚集函数,如果group by子句中带有having短语,则只有在满足指定条件的组才给输出来。

    如果有order by子句,则结果按<列名2>的值升序或降序排序。例如有表Student,其值如下:

    mysql> select * from Student;
    +--------+--------+------+------+-------+
    | Sno | Sname | Ssex | Sage | Sdept |
    +--------+--------+------+------+-------+
    | sa1211 | Lily | F | 19 | MA |
    | sa1212 | ello | F | 19 | CS |
    | sa1213 | Hello | M | 20 | CS |
    | sa1214 | Shely | F | 19 | IS |
    | sa1215 | Shelly | F | 19 | CS |
    | sa1216 | 赵三 | F | 19 | CS |
    | sa1217 | 赵四 | F | 19 | CS |
    | sa1218 | 张良 | F | 19 | CS |
    | sa1219 | 张子房 | F | 19 | CS |
    +--------+--------+------+------+-------+

    1、查询经过计算的值,例如查询全体学生的姓名以及其出生年份,并用小写字母表示所在院系:

    mysql> select Sname,"year of birth:",2017-Sage,lower(Sdept)  from Student;

    +--------+----------------+-----------+--------------+
    | Sname | year of birth: | 2017-Sage | lower(Sdept) |
    +--------+----------------+-----------+--------------+
    | Lily | year of birth: | 1998 | ma |
    | ello | year of birth: | 1998 | cs |
    | Hello | year of birth: | 1997 | cs |
    | Shely | year of birth: | 1998 | is |
    | Shelly | year of birth: | 1998 | cs |
    | 赵三 | year of birth: | 1998 | cs |
    | 赵四 | year of birth: | 1998 | cs |
    | 张良 | year of birth: | 1998 | cs |
    | 张子房 | year of birth: | 1998 | cs |
    +--------+----------------+-----------+--------------+

    2、选择表中若干元组

    2.1 取消重复的行,例如查询出所有的院系,去掉重复的值,如下:

    mysql> select distinct Sdept from Student;
    +-------+
    | Sdept |
    +-------+
    | MA |
    | CS |
    | IS |
    +-------+

    2.2 查询满足条件的元组,可以通过where子句进行实现,常用的查询条件如下:

    查询条件 谓词
    比较 =,>,<,>=,<=,!=,!>,!<;NOT+上述比较运算符
    确定范围 BETWEEN AND,NOT BETWEEN AND
    确定集合 IN,NOT IN
    字符匹配 LIKE,NOT LIKE
    空值 IS FULL,IS NOT FULL
    多重条件 AND,OR,NOT

    例如查询计算机科学系(CS),数学系(MA)学生的姓名和性别。

    mysql> select Sname,Ssex from Student where Sdept in ('CS','MA');
    +--------+------+
    | Sname | Ssex |
    +--------+------+
    | Lily | F |
    | ello | F |
    | Hello | M |
    | Shelly | F |
    | 赵三 | F |
    | 赵四 | F |
    | 张良 | F |
    | 张子房 | F |
    +--------+------+

    与IN相对的谓词是NOT IN表示要查找的属性不在指定属性集合的范围内。

    字符串匹配查询,查找所有不姓“赵”的学生:

    mysql> select * from Student where Sname not like "赵%";
    +--------+--------+------+------+-------+
    | Sno | Sname | Ssex | Sage | Sdept |
    +--------+--------+------+------+-------+
    | sa1211 | Lily | F | 19 | MA |
    | sa1212 | ello | F | 19 | CS |
    | sa1213 | Hello | M | 20 | CS |
    | sa1214 | Shely | F | 19 | IS |
    | sa1215 | Shelly | F | 19 | CS |
    | sa1218 | 张良 | F | 19 | CS |
    | sa1219 | 张子房 | F | 19 | CS |
    +--------+--------+------+------+-------+

    2.3 聚集函数,sql有很多聚集函数,主要有:

    count([distinct|all]*)    统计元组个数

    count([distinct |all <列名>]) 统计一列中值的个数

    SUM([distinct |all <列名>])计算一列值的总和(需是数值类型)

    AVG([distinct |all <列名>]) 计算一列值的平均数(需是数值类型)

    MAX([distinct |all <列名>])计算一列值的最大数

    MIN([distinct |all <列名>])计算一列值的最小数

    如果指定distinct短语,表示计算时需要取消指定列中的重复值。如果不指定distinct或指定All短语(all可缺省),则表示不取消重复值。

    例如,计算每一个院系的学生个数,如下:

    mysql> select count(*),Sdept from Student group by(Sdept);
    +----------+-------+
    | count(*) | Sdept |
    +----------+-------+
    | 7 | CS |
    | 1 | IS |
    | 1 | MA |
    +----------+-------+

    选出人数大于3的院系,以及该院系的人数:

    mysql> select count(*),Sdept from Student group by(Sdept) having count(*)>3;
    +----------+-------+
    | count(*) | Sdept |
    +----------+-------+
    | 7 | CS |
    +----------+-------+

    这里先用group by进行分组,然后再用count对每一组计数。having短语给出了选择组的条件,只有满足条件的组才会被选出。

    3、连接查询

    3.1 等值连接和非等值连接查询

    根据上表中的“比较”和“范围”条件,当连接运算符为=时,表示为等值连接,使用其他运算符为非等值连接。例如,学生表student,选课表sc,这两个表的连接是通过公共属性Sno实现的。利用该属性实现的连接查询如下:

    mysql> select student.*,sc.*
    -> from student,sc
    -> where student.Sno=sc.Sno;
    +--------+-------+------+------+-------+--------+-----+-------+
    | Sno | Sname | Ssex | Sage | Sdept | Sno | Cno | Grade |
    +--------+-------+------+------+-------+--------+-----+-------+
    | sa1211 | Lily | F | 19 | MA | sa1211 | 1 | 89 |
    | sa1211 | Lily | F | 19 | MA | sa1211 | 2 | 90 |
    | sa1211 | Lily | F | 19 | MA | sa1211 | 3 | 90 |
    | sa1212 | ello | F | 19 | CS | sa1212 | 1 | 78 |
    | sa1212 | ello | F | 19 | CS | sa1212 | 3 | 90 |
    +--------+-------+------+------+-------+--------+-----+-------+

    该语句的查询过程是这样的,首先在表student中找到第一个元组,然后从头开始扫描SC表,逐一查找与student表第一个元组的Sno相等的SC元组,找到后就将student中的第一个元组与该元组拼接起来,形成结果表中的一个元组。如果SC表上的Sno建立索引的话,就不用每次扫描SC表了。

    3.2 自身连接

    连接操作不仅可以在两个表之间进行,还可以与自身进行连接,如下:

    mysql> select * from course;
    +-----+------------------+------+---------+
    | Cno | Cname | Cpno | Ccredit |
    +-----+------------------+------+---------+
    | 1 | database | 5 | 3 |
    | 2 | math | NULL | 2 |
    | 3 | INFO SYS | 1 | 2 |
    | 4 | operating system | 6 | 2 |
    | 5 | data structure | 7 | 4 |
    | 6 | data process | NULL | 4 |
    | 7 | PASCAL | 6 | 4 |
    +-----+------------------+------+---------+

    表Course中的Cpno表示的是这门课程的先行课程,查询一门课程的间接先修课如下:

    mysql> select first.Cno,second.Cpno
    -> from course first,course second
    -> where first.Cpno=second.Cno;
    +-----+------+
    | Cno | Cpno |
    +-----+------+
    | 3 | 5 |
    | 1 | 7 |
    | 4 | NULL |
    | 7 | NULL |
    | 5 | 6 |
    +-----+------+

    通过Coruse表的内容可知,3的先行课是1,而1的先行课是5,所以3的间接先行课程是5,其它分析一样。

    3.3 外连接

    先看一个例子:

     mysql> select student.Sno,Sname,Ssex,Sdept,Cno,Grade
    -> from student,sc where student.Sno=sc.Sno;//这里用的是“等值连接”
    +--------+-------+------+-------+-----+-------+
    | Sno | Sname | Ssex | Sdept | Cno | Grade |
    +--------+-------+------+-------+-----+-------+
    | sa1211 | Lily | F | MA | 1 | 89 |
    | sa1211 | Lily | F | MA | 2 | 90 |
    | sa1211 | Lily | F | MA | 3 | 90 |
    | sa1212 | ello | F | CS | 1 | 78 |
    | sa1212 | ello | F | CS | 3 | 90 |
    +--------+-------+------+-------+-----+-------+

     mysql> select student.Sno,Sname,Ssex,Sdept,Cno,Grade
    -> from student left join sc on (student.Sno=sc.Sno);//这里用的是“外连接”中的“左外连接”
    +--------+--------+------+-------+------+-------+
    | Sno | Sname | Ssex | Sdept | Cno | Grade |
    +--------+--------+------+-------+------+-------+
    | sa1211 | Lily | F | MA | 1 | 89 |
    | sa1211 | Lily | F | MA | 2 | 90 |
    | sa1211 | Lily | F | MA | 3 | 90 |
    | sa1212 | ello | F | CS | 1 | 78 |
    | sa1212 | ello | F | CS | 3 | 90 |
    | sa1213 | Hello | M | CS | NULL | NULL |
    | sa1214 | Shely | F | IS | NULL | NULL |
    | sa1215 | Shelly | F | CS | NULL | NULL |
    | sa1216 | 赵三 | F | CS | NULL | NULL |
    | sa1217 | 赵四 | F | CS | NULL | NULL |
    | sa1218 | 张良 | F | CS | NULL | NULL |
    | sa1219 | 张子房 | F | CS | NULL | NULL |
    +--------+--------+------+-------+------+-------+

     有时候想以student表为主体选出每个学生的基本情况和选课情况,如果用等值连接的话,则那些还未选课的同学的信息将不会展示出来,这时候“外连接”的作用突显出来了,我们可以用“外连接”实现该功能,外连接分为左外连接和右外连接,假设有两张表A和B,如果A左外连接B,则显示的结果是以A为主体,A的信息将会完全展示,而B中没有的信息将会显示为NULL;右连接与之相对应,如果A右外连接B,则将会完全显示B的信息。

    3.4、复合条件连接

    如果一个查询语句中,where语句中有多个连接条件,则称为“复合条件连接”。例如,查询选修2号课程且成绩在90分以上的所有学生:

    select student.Sno,Sname

    from student,sc

    where student.Sno=sc.Sno and sc.Cno='2' and sc.grade>90;

    4 嵌套查询

    如果将一个查询块嵌套在另一个查询块的where或having短语的条件中的查询称之为“嵌套查询”,嵌套查询有以下几种情况:

    4.1 带有in的嵌套查询

    嵌套查询中,子查询的结果常是一个集合,为了完成嵌套查询,常常先进行分步查询,例如,查询与“张子房”在同一个系学习的学生,可以分为以下步骤:

    第一步:查询“张子房”同学所在的系别,select Sdept from student where Sname="张子房";//结果为CS

    第二步:查询所有CS系的学生,select Sno,Sname,Sdept from student where Sdept="CS";

    综上,嵌套查询语句可以是:

    select Sno,Sname,Sdept

    from student where Sdept in ( select Sdept from student where Sname="张子房");

    这里,子查询的查询条件不依赖于父查询,称之为“不相关子查询”。

    4.2 带有比较运算符的子查询

    当子查询返回的是单值时,可以用>,<,>=,<=,!=或<>等比较运算符进行相关条件的查询。例如上句中,“张子房”只能在一个系别中,所以查询语句还可以是:

    select Sno,Sname,Sdept

    from student where Sdept = ( select Sdept from student where Sname="张子房");

    再比如,查询每个学生超过他选修课程平均成绩的课程号:

    select Sno,Cno from SC x where grade >=(

    select AVG(grade) from SC y where y.Sno=x.Sno);

    这里,内查询是一个查询所有选修课程平均成绩的,至于是哪一个学生的平均成绩是要看参数x.Sno的值,而该值是和父查询相关的,所以,这类查询称之为相关子查询

    4.3 带有ANY(SOME)或ALL谓词的子查询

    子查询返回单值时可以用比较运算符,但返回多值是要用ANY(有的系统用SOME)或ALL修饰。其语义如下:

    > ANY 大于子查询中结果中的某个值

    > ALL 大于子查询中结果中的所有值

    ...

    !=(或<>)ANY 不等于子查询中结果中的某个值

    !=(或<>)ALL 不等于子查询中结果中的所有值

    例如:查询其他系中比计算机系中所有学生年龄都小的学生姓名和年龄:

    select Sname,Sage from student where Sage < ALL( select Sage from student where Sdept="CS") and Sdept<>"CS";

    4.4 带有EXISTS谓词的子查询

    带有exists谓词的子查询不返回任何数据,只产生逻辑真“true”或逻辑假“false”。例如,查询所有选修了1号课程的学生姓名:

    select Sname from student where exists(select * from SC where Sno=student.Sno and Cno="1");

    反之,查询没有选修1号课程的学生姓名:

    select Sname from student where not exists(select * from SC where Sno=student.Sno and Cno="1");

    再比如,查询至少选修了学生200215选修的全部课程的学生号,其语义是这样的:不存在这样的课程y,学生200215选修了y,而学生x没有选。sql语句如下:

    select distinct Sno from SC x where not exists(

    select * from SC y where y.Sno='200215' and not exists(

    select * from SC z where z.Sno=x.Sno and z.Cno=y.Cno));//表示x与y选修相同课程的课程,加上前面的not exists,表示x不与y选修相同课程的课程;再加上最外层的not exists,表示不存在这样的课程,y选修了,而x不与y选修相同的课程,双重否定是肯定,表示,y选修的课程,x都有选择。

    5 集合查询

    select 语句的查询结果是元组的集合,所以,多个select查询可以进行集合操作,集合操作包括union(并)、intersect(交)、except(差)操作。这里,参与集合操作的各查询结果的列数必须相同,而且对应项的数据类型必须相同。

    5.1 union操作,表示并操作,例如,查询计算机系的学生以及年龄不大于19的学生。代码如下:

    select * from student where Sdept="CS"

    union

    select * from student where Sage<=19;

    5.2 intersect操作,表示交操作,例如查询既选修了课程1又选修了课程2的学生。代码如下:

    select Sno from SC where Cno='1'

    intersect

    select Sno from SC where Cno='2';

    5.3 except操作,表示差操作,例如查询计算机系的学生与年龄不大于19岁的学生的差集:

    select * from student where Sdept='CS'

    except

    select * from student where Sage<=19;

    其实,以上语句的效果就是查询计算机系中,年龄大于19岁的学生:

    select * from student where Sdept='CS' and Sage>19;

    以上是数据查询的总结...

  • 相关阅读:
    xml学习篇(二) ----JSON 和XML对比
    xml学习篇(一)
    在Tomcat下部署web项目
    三枪客
    在Eclipse中使用JUnit4进行单元测试(初级篇)
    在Eclipse中使用JUnit4进行单元测试(高级篇)
    在Eclipse中使用JUnit4进行单元测试(中级篇)
    hibernate学习之Hibernate API
    Hibernate学习之对象持久化
    MySQL【七】单表查询
  • 原文地址:https://www.cnblogs.com/codeMedita/p/7616432.html
Copyright © 2020-2023  润新知