笔记-4:mysql数据查询

1.创建查询表

1.1 创建班级表

含义 字段名 数据类型 宽度
班级编号 classNo 字符型 6
班级名称 className 字符型 20
所属院系 department 字符型 30
年级 grade 数值型  
班级最大人数 classNum 数值型  
classNo className department grade classNum
AC1301 会计13-1开班 会计学院 2013 35
AC1302 会计12-2班 会计学院 2013 35
CS1401 计算机14-1班 计算机学院 2014 35
IS1301 信息系统13-1班 信息学院 2013 NULL
IS1401 信息系统14-1班 信息学院 NULL 30
create table tb_class(
classNo char(6) primary key,
className varchar(20) not null UNIQUE,
department varchar(30) not null,
grade SMALLINT,
classNum TINYINT,
)ENGINE=InnoDB;
insert into tb_class(classNo,className,department,grade,classNum) 
value
(
'AC1301','会计13-1开班','会计学院','2013','35'), ('AC1302','会计12-2班','会计学院','2013','35'), ('CS1401','计算机14-1班','计算机学院','2014','35'), ('IS1301','信息系统13-1班','信息学院','2013',null), ('IS1401','信息系统14-1班','信息学院',null,'30');

1.2 创建学生表

含义 字段名 数据类型
学号 studentNo 字符型
姓名 studentName 字符型
性别 sex 字符型
出生日期 birthday 日期型
籍贯 native 字符型
民族 nation 字符型
所属班级 classNo 字符型
studentNo studentName sex birthday native nation classNo
2013110101 张晓勇 1997-12-11 山西 AC1301
2013110103 王一敏 1996-03-25 河北 AC1301
2013110201 江山 1996-09-17 内蒙古 锡伯 AC1302
2013110202 李明 1996-01-14 广西 AC1302
2013310101 黄菊 1995-09-30 北京 IS1301
2013310103 吴昊 1995-11-18 河北 IS1301
2014210101 刘涛 1997-04-03 湖南 CS1401
2014210102 郭志坚 1997-02-21 上海 CS1401
2014310101 王林 1996-10-09 河南 IS1401
2014310102 李怡然 1996-12-31 辽宁 IS1401
create table tb_student(
studentNo char(10) not null UNIQUE,
studentName varchar(20) not null,
sex char(2),
birthday date,
native varchar(20),
nation varchar(10) default '',
classNo char(6),
)ENGINE=InnoDB;
insert into tb_student(studentNo,studentName,sex,birthday,native,nation,classNo)
value
('2013110101','张晓勇','','1997-12-11','山西','','AC1301'),
('2013110103','王一敏','','1996-03-25','河北','','AC1301'),
('2013110201','江山','','1996-09-17','内蒙古','锡伯','AC1302'),
('2013110202','李明','','1996-01-14','广西','','AC1302'),
('2013310101','黄菊','','1995-09-30','北京','','IS1301'),
('2013310103','吴昊','','1995-11-18','河北','','IS1301'),
('2014210101','刘涛','','1997-04-03','湖南','','CS1401'),
('2014210102','郭志坚','','1997-02-21','上海','','CS1401'),
('2014310101','王林','','1996-10-09','河南','','IS1401'),
('2014310102','李怡然','','1996-12-31','辽宁','','IS1401');

1.3 创建课程表

含义 字段名 数据类型
课程号 courseNo 字符型
课程名 courseName 字符型
学分 credit 数值型
课时数 courseHour 数值型
开课学期 term 字符型
先修课程 priorCourse 字符型
courseNo courseName credit courseHour term priorCourse
11003 管理学 2 32 2 NULL
11005 会计学 3 48 3 NULL
21001 计算机基础 3 48 1 NULL
21002 office高级应用 3 48 2 21001
21004 程序设计 4 64 2 21001
21005 数据库 4 64 4 21004
21006 操作系统 4 64 5 21001
31001 管理信息系统 3 48 3 21004
31002 信息系统_分析与设计 2 32 4 31001
31005 项目管理 3 48 5 31001
create table tb_course(
courseNo char(6),
courseName varchar(20) not null,
credit int not null,
courseHour int not null,
term char(2),
priorCourse char(6),
constraint PK_course primary key(courseNo),
constraint FK_course foreign key(priorCourse)  references tb_course(courseNo),
constraint CK_course check(credit=courseHour/16)
)ENGINE=InnoDB;

1.4 创建成绩表

含义 字段名 数据类型
学号 studentNo 字符型
课程号 courseNo 字符型
成绩 score 数值型
studentNo courseNo score
2013110101 11003 90
2013110101 21001 86
2013110103 11003 89
2013110103 21001 88
2013110201 11003 78
2013110201 21001 92
2013110202 11003 82
2013110202 21001 85
2013310101 21004 83
2013310101 31002 68
2013310103 21004 80
2013310103 31002 76
2014210101 21004 93
2014210101 21002 89
2014210102 21002 95
2014210102 21004 88
2014310101 21001 79
2014310101 21004 80
2014310102 21001 91
2014310102 21004 87
create table tb_score(
studentNo char(10),
courseNo char(6),
score float check(score>=0 and score<=100),
constraint PK_score primary key(studentNo,course),
constraint FK_score1 foreign key(studentNo) references tb_student(studentNo),
constraint FK_score2 foreign key(courseNo) references tb_course(courseNo)
)ENGINE=InnoDB;
insert into tb_score(studentNo,courseNo,score) value(2013110101,11003,90);
insert into tb_score(studentNo,courseNo,score) value(2013110101,21001,86);
insert into tb_score(studentNo,courseNo,score) value(2013110103,11003,89);
insert into tb_score(studentNo,courseNo,score) value(2013110103,21001,88);
insert into tb_score(studentNo,courseNo,score) value(2013110201,11003,78);
insert into tb_score(studentNo,courseNo,score) value(2013110201,21001,92);
insert into tb_score(studentNo,courseNo,score) value(2013110202,11003,82);
insert into tb_score(studentNo,courseNo,score) value(2013110202,21001,85);
insert into tb_score(studentNo,courseNo,score) value(2013310101,21004,83);
insert into tb_score(studentNo,courseNo,score) value(2013310101,31002,68);
insert into tb_score(studentNo,courseNo,score) value(2013310103,21004,80);
insert into tb_score(studentNo,courseNo,score) value(2013310103,31002,76);
insert into tb_score(studentNo,courseNo,score) value(2014210101,21004,93);
insert into tb_score(studentNo,courseNo,score) value(2014210101,21004,89);
insert into tb_score(studentNo,courseNo,score) value(2014210102,21002,95);
insert into tb_score(studentNo,courseNo,score) value(2014210102,21004,88);
insert into tb_score(studentNo,courseNo,score) value(2014310101,21001,79);
insert into tb_score(studentNo,courseNo,score) value(2014310101,21004,80);
insert into tb_score(studentNo,courseNo,score) value(2014310102,21001,91);
insert into tb_score(studentNo,courseNo,score) value(2014310102,21004,87);

2.单表查询

2.1 选择字段

(1).查询指定字段

# 查询所有班级的班级编号、班级名称和所属学院。
select classNo,className,department from tb_class;
# 从班级表tb_class中查询出所有的学院名称。
select department from tb_class;
select all department from tb_class;
# 从班级表tb_class中查询出所有的学院名称(去除重复的值)。
select DISTINCT department from tb_class;
select DISTINCTROW department from tb_class;

(2).查询所有字段

# 查询全体学生的详细信息。
select * from tb_student;
select studentNo,studentName,sex,birthday,native,nation,classNo from tb_student;

(3)查询经过计算的值

# 查询全体学生的姓名、性别和年龄。
select studentName,sex,YEAR(now())-YEAR(birthday) as age from tb_student;

# YEAR(NW())-YEAR(birthday):计算表达式,用于计算学生的年龄。
# NOW():返回当前日期和时间。也可以使用CURDATE()函数返回当前日期。
# YEAR():返回指定日期对应的年份。

(4).定义字段的别名

表达式:字段名 [as] 字段别名
# 查询全体学生的姓名、性别和年龄,要求给目标表达式取别名
select studentName as '姓名',sex as '性别',YEAR(NOW())-YEAR(birthday) as '年龄' from tb_student;

2.2 选择指定记录查询

where子句常用的查询条件:

查询条件 操作符
比较 =,<>,!=,<,<=,!<,>,>=,!>
确定范围 between and,not between and
确定集合 in,not in
字符匹配 like,not like
空值 is null,is not null
多重条件 and,or

(1).比较运算符

# 查询课时大于等于48学时的课程名称及学分。
select courseName,credit,courseHour from tb_course where courseHour>=48;
select courseName,credit,courseHour from tb_course where not courseHour<48;
# 查询少数民族学生的姓名、性别、籍贯和民族。
select studentName,sex,native,nation from tb_student where nation != '';
select studentName,sex,native,nation from tb_student where nation <> '';
select studentName,sex,native,nation from tb_student where not nation='';

(2).范围查询:between...and...

# 查询出生日期在1997-01-01和1997-12-31之间的学生姓名,性别和出生日期。
select studentName,sex,birthday from tb_student where birthday between '1997-01-01' and '1997-12-31';
# 查询出生日期不在1997-01-01和1997-12-31之间的学生姓名,性别和出生日期。
select studentName,sex,birthday from tb_student where birthday not between '1997-01-01' and '1997-12-31';

(3).带in关键字的集合查询

# 查询籍贯是北京,天津和上海的学生信息。
select * from tb_student where native in ('北京','天津','上海');
# 查询籍贯不是北京,天津和上海的学生信息。
select * from tb_student where native not in ('北京','天津','上海');

(4).带like关键字的字符串匹配查询

# 查询学号为2013110201的学生的详细情况
select * from tb_student where studentNo like '2013110201';
# 查询所有姓''的学生的学号,姓名和班号。
select studentNo,studentName,classNo from tb_student where studentName like '王%';
# 查询所有不姓''的学生的学号,姓名和班号。
select studentNo,studentName,classNo from tb_student where studentName not like '王%';
# 查询姓名中包含''字的学生学号,姓名和班号。
select studentNo,studentName,classNo from tb_student where studentName like '%林%';
# 查询姓''并且姓名长度为三个中文字的学生的学号,姓名和班号。
select studentNo,studentName,classNo from tb_student where studentName like '王__';
# 查询课程号名称中含有下划线'_'的课程信息
select * from tb_course where courseName like '%#_%'ESCAPE'#';
# 关键字ESCAPE指定一个转义字符'#'。使'#'后面的'_'不再是通配符。

 (5).使用正则表达式查询

# 语法格式:
    [NOT] [REGEXP | RLIKE] <正则表达式>
选项 说明 例子 匹配值
<字符串> 匹配包含指定字符串的文本 'fa' fan,afa,faad
[ ] 匹配[ ]中的任何一个字符 '[ab]' bay,big,app
[ ^ ] 匹配不在[ ]中的任何一个字符 '[ ^ab]' desk,cool,six
^ 匹配文本的开始字符 '^b' bed,bridge,book
$ 匹配文本的结尾字符 'er$' driver,worker,farmer
. 匹配任意单个字符 b.t better,bit,bite
* 匹配0个或多个*前面指定的字符 'f*n' fn,fan,begin
+ 匹配+前面的字符1次或多次 'ba+' bat,baa,battle,bala
|n| 匹配前面的字符至少n次 'b|2|' bb,bbbb,bbbbb
# 查询课程名称中带有中文'系统'的课程信息
select * fromtb_course where courseName REGEXP '系统';
# 查询课程名称中含有'管理''信息''系统'中文字符的所有课程信息
select * from tb_course where courseName REGEXP '管理|信息|系统';

(6).带is null关键字的空值查询

# 查询缺少先行课的课程信息
select * from tb_course where priorCourse is null;
# 查询所有先行课的课程信息
select * from tb_course where priorCourse is not null;

(7).带and或or的多条件查询

# 查询学分大于等于3且学时数大于32的课程名称,学分和学时数。
select courseName,credit,courseHour from tb_course where credit>=3 and courseHour>32;
# 查询籍贯是北京或上海的学生的姓名,籍贯和民族
select studentName,native,nation from tb_student where native='北京' or native='上海';
# 查询籍贯是北京或湖南的少数民族男生的姓名,籍贯和民族
select studentName,native,nation from tb_student where (native='北京' or native='湖南') and nation!='' and sex='';

2.3 对查询结果进行排序

关键字ASC表示按升序排列,再按,关键字desc表示按降序排列。默认使用ASC
# 查询学生的姓名,籍贯和民族,并将查询结果按姓名升序排列
select studentName,native,nation from tb_student order by studentName;
# 查询学生选课成绩大于85分的学号,课程号和成绩信息,并将查询结果先按学号升序排列,再按成绩降序排列
select * from tb_score where score>85 order by studentNo,score DESC;

2.4 限制查询结果的数量

# 语法格式:
        LIMIT [位置偏移量,] 行数
# 查询成绩排名第3至第5的学生学号,课程号和成绩
select studentNo,courseNo,score from tb_score order by score DESC limit 2,3
select studentNo,courseNo,score from tb_score order by score DESC limit 3 offset 2;
(mysql5.0,使用:limit 行数 offset 位置偏移量)

3.分组聚合查询

  • 聚合函数是通过将聚合函数添加到一个带有GROUP BY分组子句的select语句中实现的。

3.1 使用聚合函数查询

mysql中常用的聚合函数:

函数名 说明
count([ DISTINCT | ALL ] * ) 统计数据表中的记录数
count([ DISTINCT | ALL ]<列名>) 统计数据表的一列中值的个数
max([ DISTINCT | ALL ]<列名>) 求数据表的一列值中的最大值
min([ DISTINC T| ALL ]<列名>) 求数据表的一列值中的最小值
sum([ DISTINCT | ALL ]<列名>) 计算数据表的一列中值的总和
avg([ DISTINCT | ALL ]<列名>) 计算数据表的一列中值的平均值
  • DISTINC:表示在计算时取消指定列中的重复值。

  • 除count(*)外,其余聚合函数都会忽略空值。

# 查询学生总人数
select count(*) from tb_student;
select count(all *) from tb_student;
# 查询选修了课程的学生总人数
select count(DISTINCT studentNo) from tb_score;
# 查询选修课程编号为‘21001’的学生平均数
select avg(score) from tb_score where courseNo='21001';
# 计算选修课程编号为‘21001’的学生最高分
select max(score) from tb_score where courseNo='21001';

3.2 分组聚合查询

# 基本语法:
    [GROUP BY 字段列表] [HAVING <条件表达式>]
# 查询各个课程号及相应的选课人数
select courseNo,count(studentNo) from tb_score GROUP BY courseNo;
# 查询每个学生的选课门数,平均分和最高分
select studentNo,count(*) 选课门数,avg(score) 平均分,max(score) 最高分 from tb_Score GROUP BY studentNo;
# 查询平均分在80分以上的每个同学的选课门数,平均分和最高分
select studentNo,count(*) 选课门数,avg(score) 平均分,max(score) 最高分 from tb_Score GROUP BY studentNo HAVING avg(score)>=80;
# 查询有2门以上(含2门)课程成绩大于88分的学生学号及(88分以上的)课程数
select studentNo,count(*) 课程数 from tb_Score where score>88 GROUP BY studentNo HAVING count(*)>=2;
# 查询所有学生选课的平均成绩,但只有当平均成绩大于80的情况下才输出
select avg(score) 平均分 from tb_score HAVING avg(score)>=80;

4.连接查询

4.1 交叉连接

  交叉连接又称为笛卡尔积,即将一张表的每一行与另一张表的每一行连接起来,返回两张表的每一行相连接后所有可能的搭配结果,但是其连接的结果会产生一些没有意义的记录。所以这种查询实际很少使用。

# 语法结构:
select * from 表1 cross json 表2;
select * from 表1,表2;
# 查询学生表与成绩表的交叉连接
select * from tb_student cross join tb_score;
select * from tb_student,tb_score;
  • 交叉连接返回的查询结果集的记录行数等于其所连接的两张表记录行数的乘积。

4.2 内连接

  内连接通过在查询中设置连接条件来移除交叉连接查询结果集中某些数据行。其目的是为了清除交叉连接中某些没有意义的数据行。

# 语法结构_1:使用INNER JSOIN的显式语法结构
select 目标表达式1,目标表达式2,.. from table [INNER JOIN] table2 ON 连接条件 [where 过滤条件];

# 语法结构_2:使用where子句定义连接条件的隐式语法结构:
select 目标表达式_1,目标表达式_2.... from table1,table2 where 连接条件 [AND 过滤条件];

(1).等值与非等值连接

# 语法结构:
    [<表名1>.]<字段名1> <比较运算符> [<表名2>.]<字段名2>
# 查询每个学生选修课程的情况
select tb_student.*,tb_score.* from tb_student,tb_score where tb_student.studentNo=tb_score.studentNo;
select tb_student.*,tb_score.* from tb_student INNER JOIN tb_score on tb_student.studentNo=tb_score.studentNo;
# 查询会计学院全体同学的学号,姓名,籍贯,班级编号和所在班级名称。
seelct studentNo,studentName,native,tb_student.classNo,className from tb_student,tb_class where tb_student.classNo = tb_class.classNo and department='会计学院';
select studentNo,studentName,native,tb_student.classNo,className from tb_student,tb_class where tb_student.classNo = tb_class.classNo and department='会计学院'; # 'tb_student.classNo=tb_class.classNo'为连接条件,department='会计学院'为筛选条件。
# 查询选修了课程名称为'程序设计'的学生学号,姓名和成绩。
select a.studentNo,studentName,score from tb_student as a,tb_course as b,tb_score as c where a.studentNo=c.studentNo and b.courseNo = c.courseNo and courseName = '程序设计';

select a.studentNo,studentName,score from tb_student as a JOIN tb_course as b JOIN tb_score as c on a.studentNo = c.studentNo and b.courseNo = c.courseNo where courseName='程序设计';

(2).自连接

   若某个表与自身进行连接,称为自表连接或自身连接,简称自连接。

# 查询与'数据库'这门课学分相同的课程信息
select a.* from tb_course as a,tb_course as b where a.credit=b.credit and b.courseName='数据库' and a.courseName!='数据库';

select a.* from tb_course as a join tb_course as b on a.credit=b.credit where b.courseName='数据库' and a.courseName!='数据库';

(3).自然连接

  自然连接只有当连接字段在两张表中的字段名都相同时才可以使用,否则返回的是笛卡尔积的结果集。

# 用自然连接查询每个学生及其选修课程的情况,要求显示学生学号,姓名,选修的课程号和成绩。
select a.studentNo,studentName,courseNo,score from tb_student as a NATURAL join tb_score b;

4.3 外连接

  外连接将连接的两张表分为基表和参考表,然后再以基表为依据返回满足和不满足连接条件的记录。

(1).左外连接

  • 以左边表为基表,返回基表的所有记录。并且与参考表中的记录进行匹配。

  • 如果左表的某些记录在右表中没有匹配的记录,则右表对应的字段值均被设置为空值NULL。

# 使用左外连接查询所有学生及其选修课程的情况,包括没有选修课程的学生,要求显示学号,姓名。性别,班号,选修的课程号和成绩。
select a.studentNo,studentName,sex,classNo,courseNo,score from tb_student as a left outer join tb_score as b on a.studentNo=b.studentNo;

(2).右外连接

  • 以右表为基表,返回基表的所有记录。并且与参考表中的记录进行匹配。

  • 如果右表的某些记录在左表中没有匹配的记录,则左表对应的字段值均被设置为空值NULL。

# 使用右外连接查询所有学生及其选修课程的情况,包括没有选修课程的学生,要求显示学号,姓名,性别,班号,选修的课程号和成绩。
select b.studentNo,studentName,sex,classNo,courseNo,score from tb_score as a right outer join tb_student as b on a.studentNo=b.studentNo;

5.子查询

   子查询也称为嵌套查询,是将一个查询语句嵌套在另一个查询语句的where子句或HAVING短语中,前者被称为内层查询或子查询,后者被称为外层查询或父查询。

5.1 带in关键字的子查询

# 查询选修了课程的学生姓名
select studentName from tb_student where tb_student.studentNo in (select DISTINCT studentNo from tb_score);
select DISTINCT studentName from tb_student.studentNo = tb_score.studentNo;(连接查询)
# 查询没有选修过课程的学生姓名

5.2 带比较运算符的子查询

  带比较运算符的子查询指父查询与子查询之间用比较运算符进行连接。当用户能够确切知道内层查询返回的是单值时,可以用比较运算符构造子查询。

# 查询班级'计算机14-1班'所有学生的学号,姓名。
select studentNo,studentName from tb_student where classNo=(select classNo from tb_class where className='计算机14-1班');
# 查询与'李明'在同一个班学习的学生学号,姓名和班号
select studentNo,studentName,classNo from tb_student where classNo=(select classNo from tb_student where studentName='李明') and studentName!='李明';
# 查询男生中比某个女生出生年份晚的学生姓名和出生年份。
select studentName,YEAR(birthday) from tb_student where sex='男 and YEAR(birthday) > any(select YEAR(birthday) from tb_student where sex='');
# 查询男生中比所有女生出生年份晚的学生姓名和出生年份。
select studentName,YEAR(birthday) from tb_student where sex='' and YEAR(birthday) > all(select YEAR(birthday) from tb_student where sex='');

5.3 带exists关键字的子查询

  使用关键字exists构造子查询时,系统对子查询进行运算以判断它是否返回结果集,如果子查询的结果集不为空,则EXISTS返回的结果为true,此时外层查询语句将进行查询;如果子查询的结果集为空,则EXISTS返回的结果为false,此时外层查询语句将不进行查询。

# 查询选修了课程号为'31002'的学生姓名
select studentName from tb_student as a where exists (select * from tb_score as b where a.studentNo = b.studentNo and courseNo='31002');
# 查询没有选修课程号为'31002'的学生姓名
select studentName from tb_student as a where not exists (select * from tb_score as b where a.studentNo = b.studentNo and courseNo='31002');
# 查询选修了全部课程的学生姓名
select studentName from tb_student as a where not exists (select * from tb_course as c where not exists (select * from tb_score where studentNo=a.studentNo and courseNo=c.courseNo));

# 将关键字NOT EXISTS成对使用,达到用双重否定表示肯定的效果,即将一个NOT EXISTS子查询嵌套在另一个NOT EXISTS子查询的where子句中。

6.联合查询

  使用UNION关键字将多个select语句的结果组合到一个结果集中,这种查询方式称为联合查询。合并时,多个select子句中对应的字段数和数据类型必须相同。

# 语法格式:
    select - from - where
    UNION [ALL]
    select - from -where
    [...UNION [ALL]
    select - from -where]

# 关键字all的作用是不去掉重复的记录,也不对结果进行排序。
# 使用UNION查询选修了'管理学''计算机基础'的学生学号
select studentNo from tb_score,tb_course where tb_score.courseNo = tb_course.courseNo and courseName='管理学' UNION select studentNo from tb_score,tb_course where tb_score.courseNo=tb_course.courseNo and courseName='计算机基础';
等价于:
select DISTINCT studentNo from tb_score,tb_course where tb_score.courseNo=tb_course.courseNo and (courseName='管理学' or courseName='计算机基础');
# 使用UNION ALL查询选修了'管理学''计算机基础'的学生学号
select studentNo from tb_score,tb_course where tb_score.courseNo = tb_course.courseNo and courseName='管理学' UNION all select studentNo from tb_score,tb_course where tb_score.courseNo=tb_course.courseNo and courseName='计算机基础';
等价于:
select studentNo from tb_score,tb_course where tb_score.courseNo=tb_course.courseNo and (courseName='管理学' or courseName='计算机基础');
  • UNION语句必须由两条及以上的select语句组成,且彼此之间使用关键字UNION分隔。

  • UNION语句中的每个SELECT子句必须包含相同的列,表达式或聚合函数。

  • 每个select子句中对应的目标列的数据类型必须兼容。

  • 第一个select子句中的目标列名称会被作为UNION语句结果集的列名称。

  • 联合查询中只能使用一条order by子句或limit子句,且它们必须置于最后一条select语句之后。

# 查询选修了'计算机基础''管理学'的学生学号。
select studentNo from tb_score,tb_course where tb_score.courseNo=tb_course.courseNo and courseName='计算机基础' and studentNo in (select studentNo from tb_score,tb_course where tb_score.courseNo=tb_course.courseNo and courseName='管理学'); 
# 查询选修了'计算机基础'但没有选修'管理学'的学生学号
select studentNo from tb_score,tb_course where tb_score.courseNo=tb_course.courseNo and courseName='计算机基础' and studentNo not in (select studentNo from tb_score,tb_course where tb_score.courseNo=tb_course.courseNo and courseName='管理学'); 

猜你喜欢

转载自www.cnblogs.com/Cyzhouke/p/11451403.html