MySQL 基础知识入门教程(二)
https://developer.aliyun.com/article/1583374?spm=a2c6h.13148508.setting.15.3cca4f0exxOUPD
8.使用LIMIT限制查询结果的数量
当执行查询数据时可能会返回很多条记录,而用户需要的数据可能只是其中的一条或者几条
查询学生表中年纪最小的3位同学 MySQL命令:
select * from student order by age asc limit 3;
运行效果展示
9.使用GROUP BY进行分组查询
GROUP BY 子句可像切蛋糕一样将表中的数据进行分组,再进行查询等操作。换言之,可通俗地理解为:通过GROUP BY将原来的表拆分成了几张小表。
接下来,我们通过一个例子开始学习GROUP BY,代码如下
-- 创建数据库 DROP DATABASE IF EXISTS mydb; CREATE DATABASE mydb; USE mydb; -- 创建员工表 CREATE TABLE employee ( id int, name varchar(50), salary int, departmentnumber int ); -- 向员工表中插入数据 INSERT INTO employee values(1,'tome',2000,1001); INSERT INTO employee values(2,'lucy',9000,1002); INSERT INTO employee values(3,'joke',5000,1003); INSERT INTO employee values(4,'wang',3000,1004); INSERT INTO employee values(5,'chen',3000,1001); INSERT INTO employee values(6,'yukt',7000,1002); INSERT INTO employee values(7,'rett',6000,1003); INSERT INTO employee values(8,'mujk',4000,1004); INSERT INTO employee values(9,'poik',3000,1001);
9.1 GROUP BY和聚合函数一起使用
统计各部门员工个数 MySQL命令:
select count(*), departmentnumber from employee group by departmentnumber;
运行效果展示
统计部门编号大于1001的各部门员工个数 MySQL命令:
select count(*), departmentnumber from employee where departmentnumber>1001 group by departmentnumber;
运行效果展示
9.2 GROUP BY和聚合函数以及HAVING一起使用
统计工资总和大于8000的部门 MySQL命令:
select sum(salary),departmentnumber from employee group by departmentnumber sum(salary)>8000;
运行效果展示
10.使用ORDER BY对查询结果排序
从表中査询出来的数据可能是无序的或者其排列顺序不是我们期望的。为此,我们可以使用ORDER BY对查询结果进行排序
其语法格式如下所示:
SELECT 字段名1,字段名2,… FROM 表名 ORDER BY 字段名1 [ASC 丨 DESC],字段名2 [ASC | DESC];
在该语法中:字段名1、字段名2是查询结果排序的依据;参数 ASC表示按照升序排序,DESC表示按照降序排序;默认情况下,按照ASC方式排序。通常情况下,ORDER BY子句位于整个SELECT语句的末尾。
查询所有学生并按照年纪大小升序排列 MySQL命令:
select * from student order by age asc;
运行效果展示
查询所有学生并按照年纪大小降序排列 MySQL命令:
select * from student order by age desc;
运行效果展示
十二、别名设置
在査询数据时可为表和字段取別名,该别名代替表和字段的原名参与查询操作。
操作的表事先已准备
1.为表取别名
在查询操作时,假若表名很长使用起来就不太方便,此时可为表取一个別名,用该别名来代替表的名称。语法格式如下所示:
SELECT * FROM 表名 [AS] 表的别名 WHERE .... ;
将student改为stu查询整表 MySQL命令:
select * from student as stu;
运行效果展示
2.为字段取别名
在查询操作时,假若字段名很长使用起来就不太方便,此时可该字段取一个別名,用该别名来代替字段的名称。语法格式如下所示:
SELECT 字段名1 [AS] 别名1 , 字段名2 [AS] 别名2 , ... FROM 表名 WHERE ... ;
将student中的name取别名为“姓名” 查询整表 MySQL命令:
select name as '姓名',id from student;
运行效果展示
十三、表的关联关系
在实际开发中数据表之间存在着各种关联关系。在此,介绍MySQL中数据表的三种关联关系。
多对一
多对一(亦称为一对多)是数据表中最常见的一种关系。例如:员工与部门之间的关系,一个部门可以有多个员工;而一个员工不能属于多个部门只属于某个部门。在多对一的表关系 中,应将外键建在多的一方否则会造成数据的冗余。
多对多
多对多是数据表中常见的一种关系。例如:学生与老师之间的关系,一个学生可以有多个老师而且一个老师有多个学生。通常情况下,为了实现这种关系需要定义一张中间表(亦称为连接表)该表会存在两个外键分别参照老师表和学生表。
一对一
在开发过程中,一对一的关联关系在数据库中并不常见;因为以这种方式存储的信息通常会放在同一张表中。
接下来,我们来学习在一对多的关联关系中如果添加和删除数据。先准备一些测试数据,代码如下:
DROP TABLE IF EXISTS student; DROP TABLE IF EXISTS class; -- 创建班级表 CREATE TABLE class( cid int(4) NOT NULL PRIMARY KEY, cname varchar(30) ); -- 创建学生表 CREATE TABLE student( sid int(8) NOT NULL PRIMARY KEY, sname varchar(30), classid int(8) NOT NULL ); -- 为学生表添加外键约束 ALTER TABLE student ADD CONSTRAINT fk_student_classid FOREIGN KEY(classid) REFERENCES class(cid); -- 向班级表插入数据 INSERT INTO class(cid,cname)VALUES(1,'Java'); INSERT INTO class(cid,cname)VALUES(2,'Python'); -- 向学生表插入数据 INSERT INTO student(sid,sname,classid)VALUES(1,'tome',1); INSERT INTO student(sid,sname,classid)VALUES(2,'lucy',1); INSERT INTO student(sid,sname,classid)VALUES(3,'lili',2); INSERT INTO student(sid,sname,classid)VALUES(4,'domi',2);
1.关联查询
查询Java班的所有学生 MySQL命令:
select * from student where classid=(select cid from class where cname='Java');
运行效果展示
2.关于关联关系的删除数据
请从班级表中删除Java班级。在此,请注意:班级表和学生表之间存在关联关系;要删除Java班级,应该先删除学生表中与该班相关联的学生。否则,假若先删除Java班那么学生表中的cid就失去了关联
删除Java班 MySQL命令:
delete from student where classid=(select cid from class where cname='Java'); delete from class where cname='Java';
运行效果展示
十四、多表连接查询
1.交叉连接查询
交叉连接返回的结果是被连接的两个表中所有数据行的笛卡儿积;比如:集合A={a,b},集合B={0,1,2},则集合A和B的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。所以,交叉连接也被称为笛卡尔连接,其语法格式如下:
SELECT * FROM 表1 CROSS JOIN 表2;
在该语法中:CROSS JOIN用于连接两个要查询的表,通过该语句可以查询两个表中所有的数据组合。
由于这个交叉连接查询在实际运用中没有任何意义,所以只做为了解即可
2.内连接查询
内连接(Inner Join)又称简单连接或自然连接,是一种非常常见的连接查询。内连接使用比较运算符对两个表中的数据进行比较并列出与连接条件匹配的数据行,组合成新的 记录。也就是说在内连接查询中只有满足条件的记录才能出现在查询结果中。其语法格式如下:
SELECT 查询字段1,查询字段2, ... FROM 表1 [INNER] JOIN 表2 ON 表1.关系字段=表2.关系字段
在该语法中:INNER JOIN用于连接两个表,ON来指定连接条件;其中INNER可以省略。
准备数据,代码如下:
-- 若存在数据库mydb则删除 DROP DATABASE IF EXISTS mydb; -- 创建数据库mydb CREATE DATABASE mydb; -- 选择数据库mydb USE mydb; -- 创建部门表 CREATE TABLE department( did int (4) NOT NULL PRIMARY KEY, dname varchar(20) ); -- 创建员工表 CREATE TABLE employee ( eid int (4) NOT NULL PRIMARY KEY, ename varchar (20), eage int (2), departmentid int (4) NOT NULL ); -- 向部门表插入数据 INSERT INTO department VALUES(1001,'财务部'); INSERT INTO department VALUES(1002,'技术部'); INSERT INTO department VALUES(1003,'行政部'); INSERT INTO department VALUES(1004,'生活部'); -- 向员工表插入数据 INSERT INTO employee VALUES(1,'张三',19,1003); INSERT INTO employee VALUES(2,'李四',18,1002); INSERT INTO employee VALUES(3,'王五',20,1001); INSERT INTO employee VALUES(4,'赵六',20,1004);
查询员工姓名及其所属部门名称 MySQL命令:
select employee.ename,department.dname from department inner join employee on department.did=employee.departmentid;
运行效果展示
3.外连接查询
在使用内连接查询时我们发现:返回的结果只包含符合查询条件和连接条件的数据。但是,有时还需要在返回查询结果中不仅包含符合条件的数据,而且还包括左表、右表或两个表中的所有数据,此时我们就需要使用外连接查询。外连接又分为左(外)连接和右(外)连接。其语法格式如下:
SELECT 查询字段1,查询字段2, ... FROM 表1 LEFT | RIGHT [OUTER] JOIN 表2 ON 表1.关系字段=表2.关系字段 WHERE 条件
由此可见,外连接的语法格式和内连接非常相似,只不过使用的是LEFT [OUTER] JOIN、RIGHT [OUTER] JOIN关键字。其中,关键字左边的表被称为左表,关键字右边的表被称为右表;OUTER可以省略。
在使用左(外)连接和右(外)连接查询时,查询结果是不一致的,具体如下:
1、LEFT [OUTER] JOIN 左(外)连接:返回包括左表中的所有记录和右表中符合连接条件的记录。
2、RIGHT [OUTER] JOIN 右(外)连接:返回包括右表中的所有记录和左表中符合连接条件的记录。
先准备数据,代码如下:
-- 若存在数据库mydb则删除 DROP DATABASE IF EXISTS mydb; -- 创建数据库mydb CREATE DATABASE mydb; -- 选择数据库mydb USE mydb; -- 创建班级表 CREATE TABLE class( cid int (4) NOT NULL PRIMARY KEY, cname varchar(20) ); -- 创建学生表 CREATE TABLE student ( sid int (4) NOT NULL PRIMARY KEY, sname varchar (20), sage int (2), classid int (4) NOT NULL ); -- 向班级表插入数据 INSERT INTO class VALUES(1001,'Java'); INSERT INTO class VALUES(1002,'C++'); INSERT INTO class VALUES(1003,'Python'); INSERT INTO class VALUES(1004,'PHP'); -- 向学生表插入数据 INSERT INTO student VALUES(1,'张三',20,1001); INSERT INTO student VALUES(2,'李四',21,1002); INSERT INTO student VALUES(3,'王五',24,1002); INSERT INTO student VALUES(4,'赵六',23,1003); INSERT INTO student VALUES(5,'Jack',22,1009);
准备这组数据有一定的特点,为的是让大家直观的看出左连接与右连接的不同之处
1、班级编号为1004的PHP班级没有学生
2、学号为5的学生王跃跃班级编号为1009,该班级编号并不在班级表中
3.1 左(外)连接查询
左(外)连接的结果包括LEFT JOIN子句中指定的左表的所有记录,以及所有满足连接条件的记录。如果左表的某条记录在右表中不存在则在右表中显示为空。
查询每个班的班级ID、班级名称及该班的所有学生的名字 MySQL命令:
select class.cid,class.cname,student.sname from class left outer join student on class.cid=student.classid;
运行效果展示
展示结果分析:
1、分别找出Java班、C++班、Python班的学生
2、右表的王跃跃不满足查询条件故其没有出现在查询结果中
3、虽然左表的PHP班没有学生,但是任然显示了PHP的信息;但是,它对应的学生名字为NULL
3.2 右(外)连接查询
右(外)连接的结果包括RIGHT JOIN子句中指定的右表的所有记录,以及所有满足连接条件的记录。如果右表的某条记录在左表中没有匹配,则左表将返回空值。
查询每个班的班级ID、班级名称及该班的所有学生的名字 MySQL命令:
select class.cid,class.cname,student.sname from class right outer join student on class.cid=student.classid;
运行效果展示
展示结果分析:
1、分别找出Java班、C++班、Python班的学生
2、左表的PHP班不满足查询条件故其没有出现在查询结果中
3、虽然右表的jack没有对应班级,但是任然显示王跃跃的信息;但是,它对应的班级以及班级编号均为NULL
十五、子查询
子查询是指一个查询语句嵌套在另一个查询语句内部的查询;该查询语句可以嵌套在一个 SELECT、SELECT…INTO、INSERT…INTO等语句中。在执行查询时,首先会执行子查询中的语句,再将返回的结果作为外层查询的过滤条件。在子査询中通常可以使用比较运算符和IN、EXISTS、ANY、ALL等关键字。
准备数据,代码如下:
DROP TABLE IF EXISTS student; DROP TABLE IF EXISTS class; -- 创建班级表 CREATE TABLE class( cid int (4) NOT NULL PRIMARY KEY, cname varchar(20) ); -- 创建学生表 CREATE TABLE student ( sid int (4) NOT NULL PRIMARY KEY, sname varchar (20), sage int (2), classid int (4) NOT NULL ); -- 向班级表插入数据 INSERT INTO class VALUES(1001,'Java'); INSERT INTO class VALUES(1002,'C++'); INSERT INTO class VALUES(1003,'Python'); INSERT INTO class VALUES(1004,'PHP'); INSERT INTO class VALUES(1005,'Android'); -- 向学生表插入数据 INSERT INTO student VALUES(1,'张三',20,1001); INSERT INTO student VALUES(2,'李四',21,1002); INSERT INTO student VALUES(3,'王五',24,1003); INSERT INTO student VALUES(4,'赵六',23,1004); INSERT INTO student VALUES(5,'小明',21,1001); INSERT INTO student VALUES(6,'小红',26,1001); INSERT INTO student VALUES(7,'小亮',27,1002);
1.带比较运算符的子查询
比较运算符前面我们提到过得,就是>、<、=、>=、<=、!=等
查询张三同学所在班级的信息 MySQL命令:
select * from class where cid=(select classid from student where sname='张三');
运行效果展示
查询比张三同学所在班级编号还大的班级的信息 MySQL命令:
select * from class where cid>(select classid from student where sname='张三');
运行效果展示
2.带EXISTS关键字的子查询
EXISTS关键字后面的参数可以是任意一个子查询, 它不产生任何数据只返回TRUE或FALSE。当返回值为TRUE时外层查询才会 执行
假如王五同学在学生表中则从班级表查询所有班级信息 MySQL命令:
select * from class where exists (select * from student where sname='王五');
运行效果展示
3.带ANY关键字的子查询
ANY关键字表示满足其中任意一个条件就返回一个结果作为外层查询条件。
查询比任一学生所属班级号还大的班级编号 MySQL命令:
select * from class where cid > any (select classid from student);
运行效果展示
4.带ALL关键字的子查询
ALL关键字与ANY有点类似,只不过带ALL关键字的子査询返回的结果需同时满足所有内层査询条件。
查询比所有学生所属班级号还大的班级编号 MySQL命令:
select * from class where cid > all (select classid from student);
运行效果展示
总结
重要(从关键字分析):
查询语句的书写顺序和执行顺序
select ===> from ===> where ===> group by ===> having ===> order by ===> limit
查询语句的执行顺序
from ===> where ===> group by ===> having ===> select ===> order by ===> limi