mySQL教程 第4章 数据查询

来源:互联网 发布:nginx 安全加固 编辑:程序博客网 时间:2024/04/29 04:51

第4章 数据查询

mySQL运算符

这些运算符在SQL查询中用得到。

算数运算符

+ 加

- 减

* 乘

/ DIV 除

% MOD 取余数

比较运算符

= 等于

<> != 不等于

<

<=

>

>=

Between 指定范围

In 存在于集合

Is null 为NULL

Is not null 不为空

Like 通配符

Regexp rlike 正则表达式

比如

比较运算符,返回的结果 真为1,假为0

clip_image001

clip_image002

clip_image003

clip_image004

clip_image005

clip_image006

运算符优先级

最高------------------------------------------à最低

! () * / div % mod - + = <>= like between case when then else not and or

clip_image007

单表查询

查询所有列所有行

select * from TStudent

clip_image008

查询指定列

select studentID,Sname,Sex,cardID from TStudent

clip_image009

为列指定别名

select studentID 学号,Sname 姓名,Sex 性别,cardID ***号 from TStudent

clip_image010

指定查询条件

查询条件中可以使用< > <= >= != 比较运算符

1. 查询网络班学生

select studentID 学号,Sname 姓名,Sex 性别,cardID ***号,class 班级

from TStudent where class='网络与网站开发'

clip_image011

2. 查询网络班性别是女的学生

select studentID 学号,Sname 姓名,Sex 性别,cardID ***号,class 班级

from TStudent where class='网络与网站开发' and sex='女'

clip_image012

3. 查找软件测试班或性别是女的学生

select studentID 学号,Sname 姓名,Sex 性别,cardID ***号,class 班级 from TStudent where class='软件测试' or Sex='女'

clip_image013

4. 使用like模糊查询

使用字符比较符 like

% 0个或多个字符串

_ 任何单个的字符

[]在指定区域或集合内的任何单个字符

[^]不在指定区域或集合内的任何单个字符

查找姓名中含有“立”字的学生

select studentID 学号,Sname 姓名,Sex 性别,cardID ***号,class 班级 from TStudent where Sname like '%茂%'

clip_image014

思考:查找姓名最后一个字是“茂”的同学,写出SQL语句。

5. 查找姓名是“韩立刚”,“韩旭”的学生

记下上面查询结果的两个名字。查找这两个名字的记录。

select studentID 学号,Sname 姓名,Sex 性别,cardID ***号,class 班级 from TStudent where Sname in ('赵俊茂','魏清茂')

clip_image015

6. 查找出1975年到1980年出生的学生

使用比较操作符 = > < >= <= <>

select studentID 学号,Sname 姓名,Sex 性别,cardID ***号,class 班级,Birthday 生日

from TStudent where Birthday>'1980' and Birthday<'1985'

clip_image016

7. 使用关系运算符

关系运算符优先级 not and or 如下面的例子 去掉括号结果一样

select studentID 学号,Sname 姓名,Sex 性别,cardID ***号,class 班级,Birthday 生日

from TStudent where Birthday>'19820101' and Birthday<'19841230' or sex='女'

clip_image017

通过使用括号更运算顺序

select studentID 学号,Sname 姓名,Sex 性别,cardID ***号,class 班级,Birthday 生日

from TStudent where Birthday>'19820101' and (Birthday<'19841230' or sex='女')

clip_image018

8. 查询在一定范围内的值

查找生日在1985年到1990年之间的学生

select studentID 学号,Sname 姓名,Sex 性别,cardID ***号,class 班级,Birthday 生日

from TStudent where Birthday BETWEEN '19850000' and '19860000'

clip_image019

查找不在1985年到1986年出生的学生

select studentID 学号,Sname 姓名,Sex 性别,cardID ***号,class 班级,Birthday 生日

from TStudent where Birthday not BETWEEN '19850000' and '19860000'

clip_image020

尽量使用between而不使用and和比较操作符表示的表达式

如果想返回不在指定区域的行时,使用not between。这样会降低数据查询的速度。

9. 查询空值

insert into TStudent (studentid,sname) values ('19999','张永超')

select * from TStudent where studentid='19999'

clip_image021

可以看到没有插入的列值为Null

select * from TStudent where cardID is NULL

clip_image021[1]

你绝不要这样写

select * from TStudent where cardID=''

使用is not null来查询指定列中非空的行

select * from TStudent where cardID is not NULL

格式化结果集

1. 排序

默认是降序 desc升序 asc 降序

select * from TStudent order by cardID

clip_image022

select * from TStudent order by cardID asc

按两列排序 先按班级排序 再按学号排序

select * from TStudent order by Class,studentid desc

clip_image023

以下命令就是按第7列和第1列排序,输出结果和以上的一样

select * from TStudent order by 7,1 desc

2. 消除重复的行

以下命令查看有几个班

select DISTINCT class 班级 from TStudent

clip_image024

多表查询

在TStudent表插入两个学生

insert into TStudent values ('90006','张勇','男','132302198903044565','19880203','zhangyong@onest.net','JAVA','20120803');

insert into TStudent values ('90007','赵洁','女','132302198905044565','19880503','zhaojie@onest.net','JAVA','20120803')

这两个学生没有成绩

3. 使用Join内连接多张表

内连接使用inner关键字,可以省去。

没有成绩的学生没有列出来。

使用外键匹配可以讲多个表组成一张大表,可以看到组成的大表记录条数4个学生*2科

select a.*,b.*,c.* 分数 FROM `TStudent` a inner join `TScore` b on a.`StudentID`=b.`StudentID` inner join `TSubject` c on b.`subJectID`=c.`subJectID`

clip_image025

从以上三个表组成的大表找到计算机网络课程分数大于80分的记录

select sname 姓名,sex 性别,c.`subJectName` 学科,b.`mark` 分数 FROM `TStudent` a join `TScore` b on a.`StudentID`=b.`StudentID` join `TSubject` c on b.`subJectID`=c.`subJectID` where c.`subJectName`='计算机网络' and b.`mark`>80

clip_image026

可以看到输出结果来自三张表

4. 左连接

做连接使用left有连接使用right

select a.*,b.* FROM `TStudent` a left join `TScore` b on a.`StudentID`=b.`StudentID`使用左连接可以看到没有成绩学生也出现在表中

clip_image027

思考:左连接

5. 自连接

自己连接自己,比如查找重名的学生

select a.studentid,a.sname,b.studentid,b.sname from TStudent a join TStudent b on a.sname=b.sname where a.studentid<>b.studentid

clip_image028

6. 使用子查询

使用子查询,输出结果只能来自一张表,其他表作为查询的条件。

为什么使用子查询---子查询可以把一个复杂的查询分解成一系列逻辑步骤,这样就可以用一个单个的语句解决复杂的查询问题。

为什么使用连接而不使用子查询---执行效力差不多,子查询可能要求查询优化器执行额外的操作,比如排序,而这些操作将会影响查询的处理策略。

select sname 姓名 from `TStudent` where Studentid in (select StudentID from `TScore` where mark>90)

clip_image029

以下SQL语句子查询中又嵌套了子查询,查询计算机网络,输出结果只能来自一个表。

select sname 姓名 from `TStudent` where Studentid in (select StudentID from `TScore` where mark>90 and subjectID in (select subjectID from `TSubject` where subJectName='计算机网络'))

clip_image030

7. 使用any关键字

创建两个表

create table tb1 (num int not null);

create table tb2 (num int not null);

插入数据

insert into tb1 VALUES (2),(5),(13),(25),(32);

insert into tb2 VALUES (6),(8),(20),(43),(70),(4);

查找tb1,条件是只要值大于tb2的任何一个值就可以

select num from tb1 where num>any(select num from tb2)

clip_image031

8. 使用关键字all

返回tb2所有值都小的值

select num from tb1 where num<all(select num from tb2)

clip_image032

9. 使用exist关键字

如果成绩表中的分数有大于80分的记录,就返回TStudent表中的第一条记录

当然也可以使用not exist

select * from `TStudent` where EXISTS (select * from `TScore` where mark>80) limit 1

clip_image033

有大于100分的学生,就查出学生记录。

select * from `TStudent` where EXISTS (select * from `TScore` where mark>100) limit 1

clip_image034

10. 使用union合并查询结果

查找tb1和tb2大于40的数据

Select num from tb1 where num>40 union select num from tb2 where num>40

clip_image035

数据分组和汇总

11. Group by进行数据汇总

如果使用聚集函数,则将对表中的所有记录的某个字段进行汇总,然后生成单个的值。如果想生成多个汇总值,同时使用聚集函数和group by 语句,联合使用having和group by子句能够使结果集只包含满足条件的记录。

计算各个班“计算机网络”平均分

select a.Class 班级,AVG(b.`mark`) 计算机网络平均分 from `TStudent` a join `TScore` b on a.`StudentID`=b.`StudentID` join `TSubject` c on b.`subJectID`=c.`subJectID` where c.`subJectName`='计算机网络' group by a.`Class`

clip_image036

Group by 必须和集合函数结合使用

12. 联合使用group by子句与having子句

Having 相当于条件

查找计算机网络课程平均分大于80分的班级

select a.Class 班级,AVG(b.`mark`) 计算机网络平均分 from `TStudent` a join `TScore` b on a.`StudentID`=b.`StudentID` join `TSubject` c on b.`subJectID`=c.`subJectID` where c.`subJectName`='计算机网络' group by a.`Class` having AVG(b.`mark`)>75

clip_image037

13. 思考题:统计各个班级所有科目的总分。

14. 查询指定的行数

使用limit显示前2行数据

select StudentID,Sname,sex,cardID from `TStudent` limit 2

clip_image038

显示从第2条记录后面的3条记录

select StudentID,Sname,sex,cardID from `TStudent` limit 2,3

clip_image039

15. 使用聚集函数统计行数

Count函数不统计Null记录

select count(*) from `TStudent`;

clip_image040

select count(cardID) 登记了***的学生数量 from `TStudent`,没有登记***不统计。

clip_image041

16. 思考:统计男生数量

使用正则表达式

一个正则表达式中的可以使用以下保留字

符号

说明

^

所匹配的字符串以后面的字符串开头

$

所匹配的字符串以前面的字符串结尾

.

匹配任何字符(包括新行

a*

匹配任意多个a(包括空串)

a+

匹配任意多个a(不包括空串)

a?

匹配一个或零个a

de|abc

匹配de或abc

(abc)*

匹配任意多个abc(包括空串)

[a-dx]

匹配“a”、“b”、“c”、“d”或“x”

[^a-dx]

匹配除“a”、“b”、“c”、“d”、“x”以外的任何字符。“[”、“]”必须成对使用

 

17. 查询特定字符或字符串开头的记录

select sname,email from `TStudent` where email REGEXP '^KY'

clip_image042

18. 查询以特定字符或字符串结尾的记录

select sname,email from `TStudent` where sname REGEXP '富$'

clip_image043

19. 使用*和+来匹配字符串中的多个字符

*匹配前面字符任意多次,包括0次,+匹配前面字符至少一次。

select sname,email from `TStudent` where email REGEXP '^TB*'

clip_image044

select sname,email from `TStudent` where email REGEXP '^TB+'

clip_image045

20. 匹配指定字符串

select sname,email from `TStudent` where email REGEXP 'BZ'

clip_image046

21. 匹配字符串的任意一个

select sname,email from `TStudent` where emai

l REGEXP '[BZ]'

clip_image047

 

0 0