官网文档
连表查询 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集