MySQL 单表,多表,子查询知识

目录

MySQL常见的建表约束(重要)

Mysql数据查询语言(最重要)

一.单表查询

1.基本查询(后缀都是统一为from 表名)

2.排序(所谓升序和降序都是从上往下排列)

3.聚合函数

4.分组查询

5.LIMIT子句(mysql中独有的语法)

二.多表查询(最重要的)

1.内,外连接

2.左连接(左外连接)

3.右连接(右外连接)

4.全连接,mysql不支持,oracle支持

三.子查询

1.where 型子查询

2.from 型子查询

四.sql练习题(含答案)


MySQL常见的建表约束(重要)

约束名称 描述
NOT NULL 非空约束,字段不允许为null
UNIQUE 唯一约束,该字段的取值不允许重复,
PRIMARY KEY 主键约束(主关键字),自带非空、唯一、索引
FOREIGN KEY 外键约束(外关键字,有外键关联的表不能直接删除)
DEFAULT 默认值(缺省值)

Mysql数据查询语言(最重要)

重点,该语言用来查询记录,不会修改数据库和表结构。

初始化测试数据

创建测试用的表:

drop TABLE if EXISTS student;
CREATE TABLE student (
    id INT(10) PRIMARY key,
    name VARCHAR (10),
    age INT (10) NOT NULL,
    gander varchar(2)
);

drop TABLE if EXISTS course;
CREATE TABLE course (
  id INT (10)  PRIMARY key,
  name VARCHAR (10) ,
  t_id INT (10) 
) ;

drop TABLE if EXISTS teacher;
CREATE TABLE teacher(
  id INT (10)  PRIMARY key,
  name VARCHAR (10) 
);

drop TABLE if EXISTS scores;
CREATE TABLE scores(
  s_id INT ,
  score INT (10),
  c_id INT (10) ,
	PRIMARY key(s_id,c_id)
) ;

往表中插入数据:

insert into  student (id,name,age,gander)VALUES(1,'白杰',19,'男');
insert into  student (id,name,age,gander)VALUES(2,'连宇栋',19,'男');
insert into  student (id,name,age,gander)VALUES(3,'邸志伟',24,'男');
insert into  student (id,name,age,gander)VALUES(4,'李兴',11,'男');
insert into  student (id,name,age,gander)VALUES(5,'张琪',18,'男');
insert into  student (id,name,age,gander)VALUES(6,'武三水',18,'女');
insert into  student (id,name,age,gander)VALUES(7,'张志伟',16,'男');
insert into  student (id,name,age,gander)VALUES(8,'康永亮',23,'男');
insert into  student (id,name,age,gander)VALUES(9,'杨涛瑞',22,'女');
insert into  student (id,name,age,gander)VALUES(10,'王杰',21,'男');

insert into  course (id,name,t_id)VALUES(1,'数学',1);
insert into  course (id,name,t_id)VALUES(2,'语文',2);
insert into  course (id,name,t_id)VALUES(3,'c++',3);
insert into  course (id,name,t_id)VALUES(4,'java',4);
insert into  course (id,name)VALUES(5,'php');


insert into  teacher (id,name)VALUES(1,'张楠');
insert into  teacher (id,name)VALUES(2,'老孙');
insert into  teacher (id,name)VALUES(3,'薇薇姐');
insert into  teacher (id,name)VALUES(4,'磊磊哥');
insert into  teacher (id,name)VALUES(5,'大微姐');


insert into  scores (s_id,score,c_id)VALUES(1,80,1);
insert into  scores (s_id,score,c_id)VALUES(1,56,2);
insert into  scores (s_id,score,c_id)VALUES(1,95,3);
insert into  scores (s_id,score,c_id)VALUES(1,30,4);
insert into  scores (s_id,score,c_id)VALUES(1,76,5);

insert into  scores (s_id,score,c_id)VALUES(2,35,1);
insert into  scores (s_id,score,c_id)VALUES(2,86,2);
insert into  scores (s_id,score,c_id)VALUES(2,45,3);
insert into  scores (s_id,score,c_id)VALUES(2,94,4);
insert into  scores (s_id,score,c_id)VALUES(2,79,5);

insert into  scores (s_id,score,c_id)VALUES(3,65,2);
insert into  scores (s_id,score,c_id)VALUES(3,85,3);
insert into  scores (s_id,score,c_id)VALUES(3,37,4);
insert into  scores (s_id,score,c_id)VALUES(3,79,5);

insert into  scores (s_id,score,c_id)VALUES(4,66,1);
insert into  scores (s_id,score,c_id)VALUES(4,39,2);
insert into  scores (s_id,score,c_id)VALUES(4,85,3);

insert into  scores (s_id,score,c_id)VALUES(5,66,2);
insert into  scores (s_id,score,c_id)VALUES(5,89,3);
insert into  scores (s_id,score,c_id)VALUES(5,74,4);


insert into  scores (s_id,score,c_id)VALUES(6,80,1);
insert into  scores (s_id,score,c_id)VALUES(6,56,2);
insert into  scores (s_id,score,c_id)VALUES(6,95,3);
insert into  scores (s_id,score,c_id)VALUES(6,30,4);
insert into  scores (s_id,score,c_id)VALUES(6,76,5);

insert into  scores (s_id,score,c_id)VALUES(7,35,1);
insert into  scores (s_id,score,c_id)VALUES(7,86,2);
insert into  scores (s_id,score,c_id)VALUES(7,45,3);
insert into  scores (s_id,score,c_id)VALUES(7,94,4);
insert into  scores (s_id,score,c_id)VALUES(7,79,5);

insert into  scores (s_id,score,c_id)VALUES(8,65,2);
insert into  scores (s_id,score,c_id)VALUES(8,85,3);
insert into  scores (s_id,score,c_id)VALUES(8,37,4);
insert into  scores (s_id,score,c_id)VALUES(8,79,5);

insert into  scores (s_id,score,c_id)VALUES(9,66,1);
insert into  scores (s_id,score,c_id)VALUES(9,39,2);
insert into  scores (s_id,score,c_id)VALUES(9,85,3);
insert into  scores (s_id,score,c_id)VALUES(9,79,5);

insert into  scores (s_id,score,c_id)VALUES(10,66,2);
insert into  scores (s_id,score,c_id)VALUES(10,89,3);
insert into  scores (s_id,score,c_id)VALUES(10,74,4);
insert into  scores (s_id,score,c_id)VALUES(10,79,5);

一.单表查询

1.基本查询(后缀都是统一为from 表名)

(1)查询所有列:select * from 表名;其中*表示查询所有列,而不是所有行的意思。

(2)查询指定列:select 列1,列2,列n from 表名;

(3)完全重复的记录只显示一次:在查询的列之前添加distinct

(4)列运算

a.【数量类型的列】可以做加、减、乘、除:SELECT sal*5 from 表名;
说明:
1.遇到null加任何值都等于null的情况,需要用到ifnull()函数。
2.将字符串做加减乘除运算,会把字符串当作0。

b.字符串累类型可以做连续运算(需要用到concat()函数):select concat(列名1,列名2) from 表名;其中列名的类型要为字符串。

c. 给列名起别名:select 列名1 (as) 别名1,列名2 (as) 别名2 from 表名;(帮列取和帮表取别名是非常常用的)

(5)条件控制

a.条件查询。在后面添加where指定条件:`select * from 表名 where 列名=指定值;`  = < >  in (in相当于 or的一个集合)
b.【模糊查询】:当你想查询所有姓张的记录。用到【关键字like】。

select * from 表名 where 列名 like '张_';
(_代表匹配任意一个字符,%代表匹配0~n个任意字符)。

2.排序(所谓升序和降序都是从上往下排列)

  • 1.升序:select * form 表名 order by 列名 ASC ;

  • 2.降序:select * from 表名 order by 列名 DESC;

  • 3.使用多列作为排序条件: 当第一列排序条件相同时,根据第二列排序条件排序(当第二列依旧相同时可视情况根据第三例条件排序)。eg:select * from 表名 order by 列名1 ASC, 列名2 DESC;意思是当列名1的值相同时按照列名2的值降序排。

3.聚合函数

  • 1.count:select count(列名) from 表名;,记录行数。 最常用;

  • 2.max:select max(列名) from 表名;,列中最大值。select max(age) from student;

  • 3.min:select min(列名) from 表名;,列中最小值。

  • 4.sum:select sum(列名) from 表名;,求列的总值,null 和字符串默认为0。

  • 5.avg:select avg(列名) from 表名;,一列的平均值。

4.分组查询

分组查询的信息都是组的信息,不能查到个人的信息,其中查询组的信息是通过聚合函数得到的。

语法:select 分组列名,聚合函数1,聚合函数2 from 表名 group by 该分组列名;其中分组列名需要的条件是该列名中有重复的信息。

查询的结果只能为:作为分组条件的列和聚合函数;查出的信息都是组的信息。

SELECT gander,AVG(age) from student GROUP BY gander;

 反例: 这样只会把第一个数据拿出来分组:

分组查询前,还可以通过关键字where先把满足条件的人分出来,再分组。语法为:select 分组列,聚合函数 from 表名 where 条件 group by 分组列;

分组查询后,也可以通过关键字having把组信息中满足条件的组再细分出来(对组再进行条件细分只能使用having)。语法为:select 分组列,聚合函数 from 表名 where 条件 group by 分组列 having 聚合函数或列名(条件);

select gander,avg(age) avg_age,sum(age) sum_age from student GROUP BY gander HAVING  gander = '男'

5.LIMIT子句(mysql中独有的语法)

LIMIT用来限定查询结果的起始行,以及总行数。 可以用来分页查询

例如:select * from 表名 limit 4,3;表示起始行为第5行,一共查询3行记录。

--如果一个参数 说明从开始查找三条记录
SELECT id,name,age,gander FROM student limit 3
--如果两个参数 说明从第四行开始向后查三条记录(包括第四行,行数的计数是从0开始到)
SELECT id,name,age,gander FROM student limit 3,3
SELECT * FROM tbl_book LIMIT 2,3

二.多表查询(最重要的)

以后在企业中这种多表的查询是需要程序员自己手写的 ;

笛卡尔积:简单来说就是两个集合相乘的结果,集合A和集合B中任意两个元素结合在一起

1.内,外连接

内连接

内连接查询操作只列出与连接条件匹配的数据行,使用INNER JOIN或者直接使用JOIN 进行连接。

 内连接可以没有连接条件,没有条件之后的查询结果,会保留所有结果(笛卡尔集),与后面分享的交叉连接差不多。

在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复列

 查询结果,注意列数是 4 列,两张表的字段直接拼接在一起,重复的字段在后面添加数字序列以做区分;

 通俗讲就是根据条件,找到表 A 和 表 B 的数据的交集;

 例子:

普通的多表查,课内连接接通相同
SELECT * from teacher t , course c where t.id = c.t_id   
(这样会先生成笛卡尔积,效率可能略低)

SELECT * from teacher t JOIN course c on t.id = c.t_id 
SELECT * from teacher t inner JOIN course c on t.id = c.t_id 

结果:只有满足条件的会显示,5号老师没课程,5号课程没老师都不会显示  【即所有有null的数据不显示,不满足条件的也不显示,重复的数据会被覆盖只留一个】
1	王宝强	1	数学	  1
2	贾宝玉	2	语文	  2
3	温迪  3	 c++	3
4	路人甲	4	java    4

2、外连接(常用)

外连接不只列出与连接条件相匹配的行,而且还加上左表(左外连接时)或右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行。

2.左连接(左外连接)

根据条件,用右表(B)匹配左表(A),能匹配,正确保留,不能匹配其他表的字段都置空 Null

也就是,根据条件找到表 A 和 表 B 的数据的交集,再加上左表的数据集, Venn 图表示就是:

红色部分代表查询结果;

例子:

SELECT * from teacher t LEFT JOIN course c on t.id = c.t_id 
结果:只有满足条件的会显示,5号老师没课程,依然显示,5号课程没老师都不会显示,
左边表的所有数据都显示

1	王宝强	1	数学	1
2	贾宝玉	2	语文	2
3	温迪	3	c++	3
4	路人甲	4	java	4
5	路人乙			

3.右连接(右外连接)

根据条件,用左表(A)匹配右表(B),能匹配,正确保留,不能匹配其他表的字段都置空 Null

 也就是,根据条件找到表 A 和 表 B 的数据的交集,再加上右表的数据集, Venn 图表示就是:

 例子:

SELECT * from teacher t right JOIN course c on t.id = c.t_id

结果:只有满足条件的会显示,5号老师没课程不显示,5号课程没老师都,依然显示,
右边表的所有数据都显示

1	王宝强	1	数学	1
2	贾宝玉	2	语文	2
3	温迪	3	c++	3
4	路人甲	4	java	4
		    5	php	

4.全连接,mysql不支持,oracle支持

目前我的 MySQL 不支持此种方式,可以用其他方式替代解决,在此不展开。

 理论上是根据条件找到表 A 和 表 B 的数据的交集,再加上左右表的数据集:

 但是我们可以把左联合右联的结果联合起来,就可以达到取全集的结果;

select * from teacher t right join course c on t_id = c.t_id
union
select * from teacher t left join course c on t.id + c.t_id;

问题:求两张表的交集 ---内连接

求两张的并集---全连接,但是MySQL中没有全连接,所以可以使用左右连接的结果联合一下(union)

union 会把重复的内容给覆盖,只显示一个;

union all 把联合的表达数据全部合在一起,不管是否重复;

三.子查询

1.where 型子查询

将查询结果当条件

例子:查询有一门学科分数大于八十分学生信息

SELECT * from student where id in
(select DISTINCT s_id from scores where score > 90);

where 型子查询,如果是 where 列 =(内层 sql) 则内层 sql 返回的必须是单行单列,单个值。

where 型子查询,如果是 where 列 in(内层 sql) 则内层 sql 返回的必须是单列,可以多行。

2.from 型子查询

在学习 from 子查询之前,需要理解一个概念:【查询结果集在结构上可以当成表看】,那就可以当成临时表对他进行再次查询:

取排名数学成绩前五名的学生,正序排列。

select * from  (SELECT s.id,s.name,e.score,c.`name` cname from student s LEFT JOIN scores e
on s.id = e.s_id left JOIN course c on e.c_id = c.id
where c.`name` = '数学' order by e.score desc limit 5 ) t ORDER BY t.score

on后面接的是连接条件,

where后面接的是筛选条件,

group by 后面接的是分组条件;

四.sql练习题(含答案)

1、查询‘01’号学生的姓名和各科成绩,要求成绩要与课程对应。

select 
s.`name` "学生名字",
e.name "课程名称",
c.score "成绩"
from student s 
LEFT JOIN scores c 
on s.id = c.s_id
LEFT JOIN course e
on e.id = c.c_id      这个第二次左联不能直接使用and把两个on的条件直接写一起!!!
where s.id = 11

 2、查询各个学科的平均成绩,最高成绩。

SELECT c.`name`,AVG(score),MAX(score) from course c
left JOIN scores  s
on c.t_id = s.c_id 
GROUP BY c.`name`

 3、查询每个同学的最高成绩及科目名称。

-- 答案
SELECT t.`name`,MAX(c.score),cou.`name` as '学科'
FROM student t
LEFT JOIN scores c
on t.id = c.s_id
LEFT JOIN course cou
on c.c_id = cou.id
GROUP BY `name`



-- GROUP BY 如果查询的字段的结果不止一个(比如一个人会有多门课程的成绩),那么分组查询(使用这个字段分组)的结果只会显示前面的一个,那么我就可以利用分组的这个特性查询出一个人的成绩最值,以此类推;
-- 比如下面这个案列  我们是通过name来进行分组,一个人的成绩是有有多门的,但是分组后只能显示name(查询字段)的【第一个成绩】,如果不分组那么就只能查询到一个人的成绩   下面的SQL是测试这个用的
SELECT t.`name`,c.score
FROM student t
LEFT JOIN scores c
on t.id = c.s_id
GROUP BY `name`

 4、查询所有姓张的同学的各科成绩。

SELECT stu.`name`,s.score,c.`name` AS '课程'
FROM student stu
LEFT JOIN scores s
on stu.id = s.s_id
LEFT JOIN course c
on s.c_id = c.id 
WHERE stu.name LIKE '张%'   
-- 模糊查询的条件一定要加在where后面,并且要指定那一列进行模糊查询,否则语法错误

5、查询课程编号为01且课程成绩在60分以上的学生的学号和姓名。

select s.id,s.name from student s where
s.id in (
	select c.s_id from  scores c
	where c.c_id = '1' and c.score > 60
)

 6、查询课程名称为”java”,且分数低于60的学生姓名和分数。

select s.`name`,m.score  from student s left join
(select c.s_id,c.score 
from  scores c left JOIN course t
on c.c_id = t.id 
where t.name = 'java' and c.score < 60) m
on m.s_id = s.id 
where m.s_id is not null

猜你喜欢

转载自blog.csdn.net/weixin_53142722/article/details/124238584