【MySQL】联合查询(上)_mysql联表查询
目录
一. 什么是联合查询
二. 笛卡尔积
三. 内连接查询
示例演示
四. 外连接
示例演示
五. 自连接
自连接
示例演示
一. 什么是联合查询
在之前学习的增删改查中都是对于单表进行查询,但是因为在数据库设计时需要遵循范式的要求,数据就会被拆分到多张表中,那么此时需要查询一条完整的信息,就需要从多张表中获取数据最终返回给用户,此时就需要使用联合查询。
示例:查询学生信息和学生的班级信息
此时就需要将学生表和班级表建立关联,通过联合查询同时得到两张表中的信息。
二. 笛卡尔积
什么是笛卡尔积,笛卡尔积其实就是将关联的表进行数据全排列得出的结果集存放在一张临时表中。
查看笛卡尔积的语法:
select *from table1_name,table2_name;
上表就是学生表和班级表生成的笛卡尔积,只有圈起来的是有效数据,其他的都是数据全排列产生 的无效数据,那么我们联合查询其实就是在这个笛卡尔积中取出我们需要的有效数据啦。
联合查询表的个数越多,表中的数据量越⼤,临时表就会越⼤,所以根据实际情况确定联合查询表的个数,在我们的企业中一般不会联合查询超过3张表
三. 内连接查询
内连接是通过比较连接条件中指定列的值,将不同表中的相互匹配的行组合在一起,生成一张包含多张表相关数据的结果集,只有满足条件的数据才会被包含在结果集中,不满足条件的的行将被排除。
内连接查询的语法:
方法1:select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其他条件;方法2:select 字段 from 表1 别名1, join 表2 别名2 on 连接条件 where 其他条件
构建测试数据:
-- 重新创建学生表create table student( id BIGINT PRIMARY KEY auto_increment, name varchar(20), sno varchar(20) comment\'学号\', age INT, gender char(1), class_id BIGINT);-- 创建课程表create table course( id BIGINT PRIMARY KEY auto_increment, name varchar(20));-- 创建成绩表create table score( sco FLOAT, student_id BIGINT, course_id BIGINT);-- 创建班级表CREATE table class( id BIGINT PRIMARY KEY auto_increment, name varchar(20));-- 添加班级数据insert into class values(null,\'软件班\'),(null,\'机械班\'),(null,\'电子班\');-- 添加学生表数据insert into student (name, sno, age, gender, class_id) values(\'唐三藏\', \'100001\', 18,\'男\', 1),(\'孙悟空\', \'100002\', 18, \'女\', 1),(\'猪悟能\', \'100003\', 18, \'男\', 1),(\'沙悟净\', \'100004\', 18, \'男\', 1),(\'宋江\', \'200001\', 18, \'女\', 2),(\'武松\', \'200002\', 18, \'男\', 2),(\'李逹\', \'200003\', 18, \'男\', 2),(\'不想毕业\', \'200004\', 18,\'女\' , 2);-- 添加课程数据insert into course (name) values (\'Java\'), (\'C++\'), (\'MySQL\'), (\'操作系统\'), (\'计算机⽹络\'), (\'数据结构\');-- 添加成绩表数据insert into score (sco, 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);
查看构建信息:
mysql> select *from student;+----+--------------+--------+------+--------+----------+| id | name | sno | age | gender | class_id |+----+--------------+--------+------+--------+----------+| 1 | 唐三藏 | 100001 | 18 | 男 | 1 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 || 5 | 宋江 | 200001 | 18 | 女 | 2 || 6 | 武松 | 200002 | 18 | 男 | 2 || 7 | 李逹 | 200003 | 18 | 男 | 2 || 8 | 不想毕业 | 200004 | 18 | 女 | 2 |+----+--------------+--------+------+--------+----------+8 rows in set (0.00 sec)mysql> select *from class;+----+-----------+| id | name |+----+-----------+| 1 | 软件班 || 2 | 机械班 || 3 | 电子班 |+----+-----------+3 rows in set (0.00 sec)mysql> select *from course;+----+-----------------+| id | name |+----+-----------------+| 1 | Java || 2 | C++ || 3 | MySQL || 4 | 操作系统 || 5 | 计算机网络 || 6 | 数据结构 |+----+-----------------+6 rows in set (0.00 sec)mysql> select *from score;+------+------------+-----------+| sco | student_id | course_id |+------+------------+-----------+| 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 |+------+------------+-----------+20 rows in set (0.00 sec)
示例演示
1. 查看学生名为宋江的学生信息和班级信息:
-- 首先查看学生表和班级表的笛卡尔积mysql> select *from student,class;+----+--------------+--------+------+--------+----------+----+-----------+| id | name | sno | age | gender | class_id | id | name |+----+--------------+--------+------+--------+----------+----+-----------+| 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 3 | 电子班 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 2 | 机械班 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 1 | 软件班 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 3 | 电子班 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 2 | 机械班 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 1 | 软件班 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 3 | 电子班 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 2 | 机械班 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 1 | 软件班 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 3 | 电子班 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 2 | 机械班 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 1 | 软件班 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 3 | 电子班 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 2 | 机械班 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 1 | 软件班 || 6 | 武松 | 200002 | 18 | 男 | 2 | 3 | 电子班 || 6 | 武松 | 200002 | 18 | 男 | 2 | 2 | 机械班 || 6 | 武松 | 200002 | 18 | 男 | 2 | 1 | 软件班 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 3 | 电子班 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 2 | 机械班 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 1 | 软件班 || 8 | 不想毕业 | 200004 | 18 | 女 | 2 | 3 | 电子班 || 8 | 不想毕业 | 200004 | 18 | 女 | 2 | 2 | 机械班 || 8 | 不想毕业 | 200004 | 18 | 女 | 2 | 1 | 软件班 |+----+--------------+--------+------+--------+----------+----+-----------+24 rows in set (0.00 sec)-- 再从笛卡尔积中筛选出有效数据mysql> select *from student stu,class c where stu.class_id=c.id;+----+--------------+--------+------+--------+----------+----+-----------+| id | name | sno | age | gender | class_id | id | name |+----+--------------+--------+------+--------+----------+----+-----------+| 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 1 | 软件班 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 1 | 软件班 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 1 | 软件班 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 1 | 软件班 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 2 | 机械班 || 6 | 武松 | 200002 | 18 | 男 | 2 | 2 | 机械班 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 2 | 机械班 || 8 | 不想毕业 | 200004 | 18 | 女 | 2 | 2 | 机械班 |+----+--------------+--------+------+--------+----------+----+-----------+8 rows in set (0.00 sec)-- 最后从这些有效数据中得出答案mysql> select *from student stu,class c where stu.class_id=c.id and stu.name=\'宋江\';+----+--------+--------+------+--------+----------+----+-----------+| id | name | sno | age | gender | class_id | id | name |+----+--------+--------+------+--------+----------+----+-----------+| 5 | 宋江 | 200001 | 18 | 女 | 2 | 2 | 机械班 |+----+--------+--------+------+--------+----------+----+-----------+1 row in set (0.00 sec)(此时的class_id和id是不需要的,我们则不需要进行输出)-- 输出最后答案mysql> select stu.name,stu.sno,stu.age,stu.gender,c.name from student stu,class c where stu.class_id=c.id and stu.name=\'宋江\';+--------+--------+------+--------+-----------+| name | sno | age | gender | name |+--------+--------+------+--------+-----------+| 宋江 | 200001 | 18 | 女 | 机械班 |+--------+--------+------+--------+-----------+1 row in set (0.00 sec)
代码分析:
2. 查询所有同学的总成绩和同学的个人信息
-- 先查看两张表的笛卡尔积mysql> select *from student stu,score;(数据量大就不放了)-- 取出笛卡尔积中的有效数据mysql> select *from student stu ,score sc where stu.id=sc.student_id;+----+-----------+--------+------+--------+----------+------+------------+-----------+| id | name | sno | age | gender | class_id | sco | student_id | course_id |+----+-----------+--------+------+--------+----------+------+------------+-----------+| 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 70.5 | 1 | 1 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 98.5 | 1 | 3 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 33 | 1 | 5 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 98 | 1 | 6 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 60 | 2 | 1 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 59.5 | 2 | 5 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 33 | 3 | 1 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 68 | 3 | 3 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 99 | 3 | 5 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 67 | 4 | 1 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 23 | 4 | 3 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 56 | 4 | 5 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 72 | 4 | 6 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 81 | 5 | 1 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 37 | 5 | 5 || 6 | 武松 | 200002 | 18 | 男 | 2 | 56 | 6 | 2 || 6 | 武松 | 200002 | 18 | 男 | 2 | 43 | 6 | 4 || 6 | 武松 | 200002 | 18 | 男 | 2 | 79 | 6 | 6 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 80 | 7 | 2 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 92 | 7 | 6 |+----+-----------+--------+------+--------+----------+------+------------+-----------+20 rows in set (0.00 sec)(此时就能找到每个同学对应的成绩)-- 那么要查看每个同学的总成绩,肯定需要对每个同学进行分组,再计算每个同学的总成绩mysql> select stu.name,count(*)from student stu ,score sc where stu.id=sc.student_id group by (stu.id);+-----------+----------+| name | count(*) |+-----------+----------+| 唐三藏 | 4 || 孙悟空 | 2 || 猪悟能 | 3 || 沙悟净 | 4 || 宋江 | 2 || 武松 | 3 || 李逹 | 2 |+-----------+----------+7 rows in set (0.00 sec)(此时就得出了每个同学的有效成绩的数量)-- 那么现在只需要将这些分组好的对应的每个同学的成绩进行相加就好了mysql> select stu.name,sum(sc.sco)as \'总分\' from student stu ,score sc where stu.id=sc.student_id group by (stu.id);+-----------+--------+| name | 总分 |+-----------+--------+| 唐三藏 | 300 || 孙悟空 | 119.5 || 猪悟能 | 200 || 沙悟净 | 218 || 宋江 | 118 || 武松 | 178 || 李逹 | 172 |+-----------+--------+7 rows in set (0.00 sec)
代码分析:
3. 查询所有同学每门课程的成绩和个人信息
-- 先查找学生表,课程表,成绩表的笛卡尔积mysql> select *from student,course,score;(这里数据量非常大,就不放了960条数据)960 rows in set (0.00 sec)-- 再从笛卡尔积中取出有效数据mysql> select *from student stu,course c,score sc where stu.id=sc.student_id and c.id=sc.course_id;+----+-----------+--------+------+--------+----------+----+-----------------+------+------------+-----------+| id | name | sno | age | gender | class_id | id | name | sco | student_id | course_id |+----+-----------+--------+------+--------+----------+----+-----------------+------+------------+-----------+| 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 1 | Java | 70.5 | 1 | 1 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 3 | MySQL | 98.5 | 1 | 3 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 5 | 计算机网络 | 33 | 1 | 5 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 6 | 数据结构 | 98 | 1 | 6 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 1 | Java | 60 | 2 | 1 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 5 | 计算机网络 | 59.5 | 2 | 5 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 1 | Java | 33 | 3 | 1 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 3 | MySQL | 68 | 3 | 3 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 5 | 计算机网络 | 99 | 3 | 5 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 1 | Java | 67 | 4 | 1 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 3 | MySQL | 23 | 4 | 3 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 5 | 计算机网络 | 56 | 4 | 5 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 6 | 数据结构 | 72 | 4 | 6 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 1 | Java | 81 | 5 | 1 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 5 | 计算机网络 | 37 | 5 | 5 || 6 | 武松 | 200002 | 18 | 男 | 2 | 2 | C++ | 56 | 6 | 2 || 6 | 武松 | 200002 | 18 | 男 | 2 | 4 | 操作系统 | 43 | 6 | 4 || 6 | 武松 | 200002 | 18 | 男 | 2 | 6 | 数据结构 | 79 | 6 | 6 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 2 | C++ | 80 | 7 | 2 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 6 | 数据结构 | 92 | 7 | 6 |+----+-----------+--------+------+--------+----------+----+-----------------+------+------------+-----------+20 rows in set (0.00 sec)-- 再将查询结果进行精简一下,得到我们需要的数据mysql> select stu.name,stu.sno,stu.age,stu.gender,c.name,sc.sco from student stu,course c,score sc where stu.id=sc.student_id and sc.course_id=c.id;+-----------+--------+------+--------+-----------------+------+| name | sno | age | gender | name | sco |+-----------+--------+------+--------+-----------------+------+| 唐三藏 | 100001 | 18 | 男 | Java | 70.5 || 唐三藏 | 100001 | 18 | 男 | MySQL | 98.5 || 唐三藏 | 100001 | 18 | 男 | 计算机网络 | 33 || 唐三藏 | 100001 | 18 | 男 | 数据结构 | 98 || 孙悟空 | 100002 | 18 | 女 | Java | 60 || 孙悟空 | 100002 | 18 | 女 | 计算机网络 | 59.5 || 猪悟能 | 100003 | 18 | 男 | Java | 33 || 猪悟能 | 100003 | 18 | 男 | MySQL | 68 || 猪悟能 | 100003 | 18 | 男 | 计算机网络 | 99 || 沙悟净 | 100004 | 18 | 男 | Java | 67 || 沙悟净 | 100004 | 18 | 男 | MySQL | 23 || 沙悟净 | 100004 | 18 | 男 | 计算机网络 | 56 || 沙悟净 | 100004 | 18 | 男 | 数据结构 | 72 || 宋江 | 200001 | 18 | 女 | Java | 81 || 宋江 | 200001 | 18 | 女 | 计算机网络 | 37 || 武松 | 200002 | 18 | 男 | C++ | 56 || 武松 | 200002 | 18 | 男 | 操作系统 | 43 || 武松 | 200002 | 18 | 男 | 数据结构 | 79 || 李逹 | 200003 | 18 | 男 | C++ | 80 || 李逹 | 200003 | 18 | 男 | 数据结构 | 92 |+-----------+--------+------+--------+-----------------+------+20 rows in set (0.00 sec)
代码分析:
四. 外连接
外连接分为左外连接、右外连接和全外连接三种类型,但是我们的MySQL不支持全外连接,所以这里我们就将一下左连接和右连接。
- 左外连接:返回左表中所有记录和右表中与左表匹配的记录,如果右表中没有匹配的记录,那么结果集中的对应字段就会显示为NULL
- 右外连接:与左外连接相反,返回右表的所有记录和左表中匹配的记录。如果左表中没有匹配的记录,则结果集中对应字段会显⽰为NULL。
左外连接和右外连接的语法:
-- 左外连接select 字段 from 表名1 left join 表名2 on 连接条件-- 右外连接select 字段 from 表名1 right join 表名2 on 连接条件
示例演示
1.查询没有参加考试的学生:
-- 通过左外连接,将两张表中的有效数据连接起来mysql> select *from student stu left join score sc on sc.student_id=stu.id;+----+--------------+--------+------+--------+----------+------+------------+-----------+| id | name | sno | age | gender | class_id | sco | student_id | course_id |+----+--------------+--------+------+--------+----------+------+------------+-----------+| 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 98 | 1 | 6 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 33 | 1 | 5 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 98.5 | 1 | 3 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 70.5 | 1 | 1 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 59.5 | 2 | 5 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 60 | 2 | 1 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 99 | 3 | 5 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 68 | 3 | 3 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 33 | 3 | 1 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 72 | 4 | 6 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 56 | 4 | 5 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 23 | 4 | 3 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 67 | 4 | 1 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 37 | 5 | 5 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 81 | 5 | 1 || 6 | 武松 | 200002 | 18 | 男 | 2 | 79 | 6 | 6 || 6 | 武松 | 200002 | 18 | 男 | 2 | 43 | 6 | 4 || 6 | 武松 | 200002 | 18 | 男 | 2 | 56 | 6 | 2 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 92 | 7 | 6 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 80 | 7 | 2 || 8 | 不想毕业 | 200004 | 18 | 女 | 2 | NULL | NULL | NULL |+----+--------------+--------+------+--------+----------+------+------------+-----------+21 rows in set (0.00 sec)(那么此时可以看到,不想毕业这个同学的成绩为NULL,那么就是我们要找的人)-- 在有效数据中查找没参加考试的同学mysql> select *from student stu left join score sc on sc.student_id=stu.id where sc.sco is null;+----+--------------+--------+------+--------+----------+------+------------+-----------+| id | name | sno | age | gender | class_id | sco | student_id | course_id |+----+--------------+--------+------+--------+----------+------+------------+-----------+| 8 | 不想毕业 | 200004 | 18 | 女 | 2 | NULL | NULL | NULL |+----+--------------+--------+------+--------+----------+------+------------+-----------+1 row in set (0.00 sec)
代码分析:
2. 查询没有学生的班级
-- 先通过右外连接的方式,将两种表的有效数据进行连接mysql> select *from student stu right join class c on stu.class_id=c.id;+------+--------------+--------+------+--------+----------+----+-----------+| id | name | sno | age | gender | class_id | id | name |+------+--------------+--------+------+--------+----------+----+-----------+| 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 1 | 软件班 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 1 | 软件班 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 1 | 软件班 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 1 | 软件班 || 8 | 不想毕业 | 200004 | 18 | 女 | 2 | 2 | 机械班 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 2 | 机械班 || 6 | 武松 | 200002 | 18 | 男 | 2 | 2 | 机械班 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 2 | 机械班 || NULL | NULL | NULL | NULL | NULL | NULL | 3 | 电子班 |+------+--------------+--------+------+--------+----------+----+-----------+9 rows in set (0.00 sec)(此时可以看见电子版的学生信息都为空,那么电子班就是没有学生的班级咯)-- 取出学生信息为空的班级mysql> select *from student stu right join class c on stu.class_id=c.id where stu.id is null;+------+------+------+------+--------+----------+----+-----------+| id | name | sno | age | gender | class_id | id | name |+------+------+------+------+--------+----------+----+-----------+| NULL | NULL | NULL | NULL | NULL | NULL | 3 | 电子班 |+------+------+------+------+--------+----------+----+-----------+1 row in set (0.00 sec)
代码分析:
五. 自连接
大家可以想一下,如果我想要让比较学生每科成绩的分数,我可以跨行进行比较吗?这显然是不行的,这个时候就要用到我们的自连接(实现行与行之间的比较)
mysql> select *from student,score where student.id=score.student_id;+----+-----------+--------+------+--------+----------+------+------------+-----------+| id | name | sno | age | gender | class_id | sco | student_id | course_id |+----+-----------+--------+------+--------+----------+------+------------+-----------+| 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 70.5 | 1 | 1 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 98.5 | 1 | 3 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 33 | 1 | 5 || 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 98 | 1 | 6 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 60 | 2 | 1 || 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 59.5 | 2 | 5 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 33 | 3 | 1 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 68 | 3 | 3 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 99 | 3 | 5 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 67 | 4 | 1 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 23 | 4 | 3 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 56 | 4 | 5 || 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 72 | 4 | 6 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 81 | 5 | 1 || 5 | 宋江 | 200001 | 18 | 女 | 2 | 37 | 5 | 5 || 6 | 武松 | 200002 | 18 | 男 | 2 | 56 | 6 | 2 || 6 | 武松 | 200002 | 18 | 男 | 2 | 43 | 6 | 4 || 6 | 武松 | 200002 | 18 | 男 | 2 | 79 | 6 | 6 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 80 | 7 | 2 || 7 | 李逹 | 200003 | 18 | 男 | 2 | 92 | 7 | 6 |+----+-----------+--------+------+--------+----------+------+------------+-----------+20 rows in set (0.00 sec)
自连接
⾃连接是⾃⼰与⾃⼰取笛卡尔积,可以把⾏转化成列,在查询的时候可以使⽤where条件对结果进⾏过滤,或者说实现⾏与⾏之间的⽐较。在做表连接时为表起不同的别名
查看自己与自己取笛卡尔积:
通过这样的方式就可以将行与行之间数据转换成列与列之间的数据,那么就可以进行比较了~
示例演示
1.找出所有“MySQL”成绩比java成绩高的学生信息和成绩信息
-- 将成绩表与成绩表进行自连接后,对应的数据进行连接,进行比较mysql> select *from student stu,score s1,score s2 where stu.id=s1.student_id and s1.student_id=s2.student_id and s1.course_id=3 and s2.course_id=1 and s1.sco>s2.sco;+----+-----------+--------+------+--------+----------+------+------------+-----------+------+------------+-----------+| id | name | sno | age | gender | class_id | sco | student_id | course_id | sco | student_id | course_id |+----+-----------+--------+------+--------+----------+------+------------+-----------+------+------------+-----------+| 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 98.5 | 1 | 3 | 70.5 | 1 | 1 || 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 68 | 3 | 3 | 33 | 3 | 1 |+----+-----------+--------+------+--------+----------+------+------------+-----------+------+------------+-----------+2 rows in set (0.00 sec)mysql> select stu.name,stu.sno,stu.gender,s1.sco as \'MySQL成绩\',s2.sco as \'Java成绩\' from student stu,score s1,score s2 where stu.id=s1.student_id and s1.student_id=s2.student_id and s1.course_id=3 and s2.course_id=1 and s1.sco>s2.sco;+-----------+--------+--------+-------------+------------+| name | sno | gender | MySQL成绩 | Java成绩 |+-----------+--------+--------+-------------+------------+| 唐三藏 | 100001 | 男 | 98.5 | 70.5 || 猪悟能 | 100003 | 男 | 68 | 33 |+-----------+--------+--------+-------------+------------+2 rows in set (0.00 sec)
代码分析:
2. 找出所有MySQL成绩比Java成绩高的学生信息和班级信息和成绩信息
此时就找出了成绩表1中为MySQL成绩和成绩表2中为Java成绩的对应的学生信息和班级信息和成绩信息,此时只需要对当前结果集中的MySQL成绩和Java成绩进行比较就能得出最终答案: