1.自连接
自连接是指在同一张表连接自身进行查询。是把自己和自己进行笛卡尔积,属于SQL中的一种技巧。 (用的不多,只是用来处理一些特殊场景的问题)
啥时候需要使用自连接? SQL指定条件,都是按照列和列之间进行指定的。自连接的本质其实是把行和行之间的比较条件,转换成列和列
1.1 创建案列表:
drop table if exists classes;
drop table if exists student;
drop table if exists course;
drop table if exists score;
create table classes (id int primary key auto_increment, name varchar(20), `desc` varchar(100));
create table student (id int primary key auto_increment, sn varchar(20), name varchar(20), qq_mail varchar(20) ,
classes_id int);
create table course(id int primary key auto_increment, name varchar(20));
create table score(score decimal(3, 1), student_id int, course_id int);
insert into classes(name, `desc`) values
('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
('中文系2019级3班','学习了中国传统文学'),
('自动化2019级5班','学习了机械自动化');
insert into student(sn, name, qq_mail, classes_id) values
('09982','黑旋风李逵','xuanfeng@qq.com',1),
('00835','菩提老祖',null,1),
('00391','白素贞',null,1),
('00031','许仙','xuxian@qq.com',1),
('00054','不想毕业',null,1),
('51234','好好说话','say@qq.com',2),
('83223','tellme',null,2),
('09527','老外学中文','foreigner@qq.com',2);
insert into course(name) values
('Java'),('中国传统文化'),('计算机原理'),('语文'),('高阶数学'),('英文');
insert into score(score, student_id, course_id) values
(70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
(60, 2, 1),(59.5, 2, 5),
(33, 3, 1),(68, 3, 3),(99, 3, 5),
(67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
(81, 5, 1),(37, 5, 5),
(56, 6, 2),(43, 6, 4),(79, 6, 6),
(80, 7, 2),(92, 7, 6);
案列1: 显示所有“计算机原理”成绩比“Java”成绩高的成绩信息 在这个问题中,可以看到,这里的条件是按照行的方式来排列的 这个问题下的表,不同科目之间已经不是列与列了,而是行与行
为了解决这个问题,就需要把行,给转换成列 把行转换成列,就可以用到"自连接".
按照student_id进行连接条件之后产生的笛卡尔积:(注意一个表进行自连接操作时需要用as设置别名才可以操作) ,如图所示:
select * from score as s1,score as s2 where s1.student_id=s2.student_id;
本来这里的70.5和98.5是同一列的两个行: 经过了笛卡尔积之后,已经分布到两个列中了:
但是当前这里的这两列,中间还是有着不少的无效数据的.为了能够更好的进行比较,需要再加上一些筛选条件; 比如,就让s1的课程id只保留3的记录,s2的课程id只保留1的记录 :
select * from score as s1,score as s2 where s1.student_id=s2.student_id and s1.course_id=1 and s2.course_id=3;
最终答案操作即为:
select s1.student_id,s1.score,s2.score from score as s1,score as s2 where s1.student_id=s2.student_id and s1.course_id=3 and s2.course_id=1 and s1.score>s2.score;
所以ID为1和3的同学“计算机原理”成绩比“Java”成绩高
自连接的关键就是能把行转换为列!
2.子查询
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询(套娃查询) 相当于可以理解为后一条SQL语句的返回值作为前一条SQL语句的参数进行查询
- 单行子查询:返回一行记录的子查询
查询与“不想毕业” 同学的同班同学:
select * from student where classes_id=(select classes_id from student where name='不想毕业');
- 多行子查询:返回多行记录的子查询
案例:查询“语文”或“英文”课程的成绩信息
- NOT(IN)关键字
select * from score where course_id in (select id from course where
name='语文' or name='英文');
select * from score where course_id not in (select id from course where
name!='语文' and name!='英文');
in: not in: 可以使用多列包含:
insert into score(score, student_id, course_id) values
(70.5, 1, 1),(98.5, 1, 3),
(60, 2, 1);
SELECT
*
FROM
score
WHERE
( score, student_id, course_id ) IN ( SELECT score, student_id,
course_id FROM score GROUP BY score, student_id, course_id HAVING
count( 0 ) > 1 );
- [NOT] EXISTS关键字:
select * from score sco where exists (select sco.id from course cou
where (name='语文' or name='英文') and cou.id = sco.course_id);
select * from score sco where not exists (select sco.id from course cou
where (name!='语文' and name!='英文') and cou.id = sco.course_id);
- 在from子句中使用子查询:子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个
子查询当做一个临时表使用。 查询所有比“中文系2019级3班”平均分高的成绩信息:
SELECT
avg( sco.score ) score
FROM
score sco
JOIN student stu ON sco.student_id = stu.id
JOIN classes cls ON stu.classes_id = cls.id
WHERE
cls.NAME = '中文系2019级3班';
查询成绩表中,比以上临时表平均分高的成绩:
SELECT
*
FROM
score sco,
(
SELECT
avg( sco.score ) score
FROM
score sco
JOIN student stu ON sco.student_id = stu.id
JOIN classes cls ON stu.classes_id = cls.id
WHERE
cls.NAME = '中文系2019级3班'
) tmp
WHERE
sco.score > tmp.score;
3.合并查询
在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。使用UNION和UNION ALL时,前后查询的结果集中,字段需要一致。
- union
该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。 案例:查询id小于3,或者名字为“英文”的课程:
select * from course where id<3
union
select * from course where name='英文';
select * from course where id<3 or name='英文';
- union all
该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。 案例:查询id小于3,或者名字为“Java”的课程:
select * from course where id<3
union all
select * from course where name='Java';
4. MySQL表的增删改查内容重点总结
- 数据库约束
- 表的关系:
- 一对一:
- 一对多:
- 多对多:需要创建中间表来映射两张表的关系
INSERT INTO table_name [(column [, column ...])] SELECT ...
- 聚合函数:MAX、MIN、AVG、COUNT、SUM
- 分组查询:GROUP BY… HAVING …
- 内连接:
select ... from 表1,表2 where 条件
select ... from 表1 join 表2 on 条件 where 其他条件
- 外连接:
select ... from 表1 left/right join 表2 on 条件 where 其他条件
- 自连接:
select ... from 表1,表1 where 条件
select ... from 表1 join 表1 on 条件
- 子查询:
```sql
select ... from 表1 where 字段1 = (select ... from ...);
select ... from 表1 where 字段1 in (select ... from ...);
select ... from 表1 where exists (select ... from ... where 条件);
select ... from 表1, (select ... from ...) as tmp where 条件
- 合并查询:
select ... from ... where 条件
union
select ... from ... where 条件
select ... from ... where 条件
union all
select ... from ... where 条件
|