MySQL B站(20-23集)

171 阅读4分钟

官网文档

dev.mysql.com/doc/refman/…

连表查询 join

https://www.cnblogs.com/fudashi/p/7491039.html

内连接 INNER JOIN 是最常用的连接操作。从数学的角度讲就是求两个表的交集,从笛卡尔积的角度讲就是从笛卡尔积中挑出 ON 子句条件成立的记录。

左连接 LEFT JOIN 的含义就是求两个表的交集外加左表剩下的数据。

同理右连接 RIGHT JOIN 就是求两个表的交集外加右表剩下的数据。

思路

  • 我要查哪些数据 select...

  • 从哪几张表查 from 表 xxx join 连接的表 on 交叉条件

  • 假设存在一种多张表查询,慢慢来,先查询2张表,再慢慢增加

INNER JOIN,LEFT JOIN,RIGHT JOIN

-- 联表查询 :参加考试的同学(学号,姓名,科目编号,分数)
-- 姓名得去 `student` 里查,分数得去 `result` 里查
-- 学生表中的 StudentNo = 成绩表的 StudentNo

-- 用 s.StudentNo 是为了确定在 s 表里查,不然就会报模棱两可的错
SELECT s.StudentNo,StudentName,SubjectNo,StudentResult
FROM `student` AS s
INNER JOIN `result` AS r
WHERE s.StudentNo = r.StudentNo; -- where可以换为 on

-- right join
SELECT s.StudentNo,StudentName,SubjectNo,StudentResult
FROM `student` s -- as 有时候可以省略
RIGHT JOIN `result` r
ON s.studentno = r.studentno;

-- left join
-- 注意:这个方式会查出,没参加考试的学生,他们的SubjectNo,StudentResult默认为 Null
SELECT s.StudentNo,StudentName,SubjectNo,StudentResult
FROM `student` s -- as 有时候可以省略
LEFT JOIN `result` r
ON s.studentno = r.studentno;
操作描述
inner join如果表中至少有一个匹配,就会返回行
left join会从左表中返回所有的值,即使右表中没有匹配
right join会从右表中返回所有的值,即使左表中没有匹配

查is null, 查多张表

-- 查询缺考的学生

-- join (连接的表) on (判断的条件) 连接查询
-- where 等值查询
SELECT s.StudentNo,StudentName,SubjectNo,StudentResult
FROM `student` s
LEFT JOIN `result` r
ON s.studentno = r.studentno
WHERE r.StudentResult IS NULL;  
-- 这里如果是 s.WHERE r.StudentResult IS NULL就会报错。
-- 也可以直接这么写: WHERE StudentResult IS NULL


-- 查询参加考试的同学信息 (学号 学生姓名 科目名 分数) (三张表)
-- 注意这里的 sub.subjectno, 只能去 sub 表, r 表里查,不能去 s 表里查
SELECT s.studentno,StudentName,sub.subjectno,subjectname,StudentResult
FROM student s
RIGHT JOIN `result` r
ON s.studentno = r.studentno -- 查到这里之后,再连 subject 表
INNER JOIN `subject` sub
ON r.subjectno = sub.subjectno;

自连接

自己的表和自己的表连接

INSERT INTO category(categoryid,pid,categoryName)
VALUES(2,1,'信息技术'),(3,1,'软件开发'),(4,3,'数据库'),
(5,1,'美术设计'),(6,3,'web开发'),(7,5,'PS技术'),(8,2,'办公信息');

-- 自连接
SELECT a.`categoryName` AS '父栏目',b.`categoryName` AS '子栏目'
FROM `category` AS a,`category` AS b
WHERE a.`categoryid` = b.`pid`;

联表查询的练习

-- 查询学生所属的年级 (学号 学生姓名 年级名称)
SELECT studentno,studentname,gradename
FROM student
INNER JOIN grade
ON student.gradeid = grade.gradeid;


-- 查询科目所属的年级 (科目名称 年级名称)
SELECT subjectname,gradename
FROM `subject` sub
INNER JOIN grade
ON sub.gradeid = grade.gradeid;

-- 查询参加了 数据库结构-1 考试、且成绩大于90分的,同学的信息(学号 学生姓名 科目名 分数)
SELECT s.studentno,studentname,subjectname,studentresult
FROM `student` s
INNER JOIN `result` r
ON s.studentno = r.studentno
INNER JOIN `subject` sub
ON r.subjectno = sub.subjectno
WHERE sub.subjectname = '数据库结构-1' AND r.studentresult > 90;
-- 注意,一个查询语句只能有一个 WHERE,通过 and 等 增加

分页和排序

-- 排序 升序 asc, 降序 desc
-- order by 通过哪个字段排序

SELECT studentname,studentresult
FROM `student` s
INNER JOIN `result` r
ON s.studentno = r.studentno
ORDER BY studentresult asc;
-- 分页 每页显示5条
-- limit 是所有语句的最后一个
-- limit 0,5 起始值,页面的大小

-- 查询 高等数学-1 课程成绩排名前十的学生,并且分数大于80 的学生信息
SELECT s.studentno,studentname,subjectname,studentresult
FROM `student` s
INNER JOIN `result` r
ON s.studentno = r.studentno
INNER JOIN `subject` sub
ON r.subjectno = sub.subjectno
WHERE subjectname = '高等数学-1' AND studentresult > 80
LIMIT 0,10;

子查询

-- 查询分数不小于 80分 的学生学号和姓名 DISTINCT 去重

    -- 我的错误写法:
    -- SELECT DISTINCT s.studentno,studentname
    -- studentno
    -- FROM `student` s
    -- INNER JOIN `result` r
    -- ON r.studentresult >= 80;

SELECT DISTINCT s.studentno,studentname -- 不能是studentno,因为2张表都有studentno
FROM `student` s
INNER JOIN `result` r
ON s.studentno = r.studentno
WHERE r.studentresult >= 80;

-- 在上面基础上增加一个科目 高等数学-2
SELECT DISTINCT s.studentno,studentname
FROM `student` s
INNER JOIN `result` r
ON s.studentno = r.studentno
WHERE `studentresult` >= 80 AND `subjectno` = (
	SELECT `subjectno` FROM `subject`
	WHERE `subjectname` = '高等数学-2'
);

-- 如果用子查询 来 查询分数不小于 80分 的学生学号和姓名 DISTINCT 去重? 不行啊,因为
-- WHERE studentresult >= 80 会返回多行数据
SELECT DISTINCT studentno,studentname
FROM `student`
WHERE studentno = (
	SELECT studentno FROM `result`
	WHERE studentresult >= 99
);

-- 注意 子查询 必须只返回一行数据

-- 查询 高等数学-2 且分数不小于80 的同学的学号和姓名
SELECT s.studentno,studentname
FROM `student` s
INNER JOIN `result` r
ON s.studentno = r.studentno
WHERE studentresult >= 80 AND `subjectno` = (
	SELECT subjectno FROM `subject`
	WHERE subjectname = '高等数学-2'
);

-- 查询 高等数学-1 前5名同学的成绩的信息(学号 姓名 分数)
SELECT DISTINCT s.studentno,studentname,studentresult
FROM `student` s
INNER JOIN `result` r
ON s.studentno = r.studentno
WHERE subjectno = (
	SELECT subjectno FROM `subject`
	WHERE subjectname = '高等数学-1'
)
ORDER BY studentresult DESC
LIMIT 0,5

todo: 看完了23集