1,多表联查
非等值查询
语法:select * from 表1,表2
# 多表联查
-- 非等值联查
-- 笛卡尔积
SELECT * FROM student,class;
等值查询
(1)内联查询
语法:select * from 表1,表2 where 表1.字段1 = 表2.字段2...
-- 等值联查
-- 内联查询
SELECT * FROM student,class,sc WHERE student.classid = class.classid AND student.sid = sc.sid;
SELECT * FROM sc,course WHERE sc.cid = course.cid;
SELECT DISTINCT * FROM student,class,sc,teacher,course WHERE student.Sid = sc.Sid AND sc.Cid = course.Cid AND course.Tid = teacher.Tid AND student.classid = class.classid;
-- 找到张三老师教过的学生
SELECT student.Sid,Sname,birthday,Ssex,classid FROM teacher,student,sc,course
WHERE teacher.Tid = course.Tid
AND course.Cid = sc.Cid
AND sc.Sid = student.Sid
AND Tname = '张三';
-- 张三老师教过学生个数,考试平均分
SELECT COUNT(*) 学生个数 ,AVG(score) 平均分 FROM teacher,student,sc,course
WHERE teacher.Tid = course.Tid
AND course.Cid = sc.Cid
AND sc.Sid = student.Sid
AND Tname = '张三';
-- 每个老师教过的学生个数和平均分
SELECT COUNT(*) 学生个数 ,AVG(score) 平均分,teacher.Tname FROM teacher,student,sc,course
WHERE teacher.Tid = course.Tid
AND course.Cid = sc.Cid
AND sc.Sid = student.Sid GROUP BY teacher.Tid ORDER BY AVG(score) DESC;
(3)内联查询的第二种写法 inner join on
语法:select * from 表1 inner join 表2 on 条件
-- 内联的第二种写法
-- 表 INNER JOIN ON 关系
SELECT * FROM student
INNER JOIN class ON student.classid = class.classid
INNER JOIN sc ON student.Sid = sc.Sid
INNER JOIN course ON sc.Cid = course.Cid
INNER JOIN teacher ON teacher.Tid = course.Tid
WHERE Tname = '张三';
(4)外联查询 left join in 或 right join on
语法:select * from 表1 left 或 right join 表2 on 条件;
-- 外联查询要选定一个主表
-- 左外联
-- 表 LEFT JOIN 表 ON 关系
SELECT * FROM student LEFT JOIN class ON student.classid = class.classid;
-- 右外联
-- 表 RIGHT JOIN 表 ON 关系
SELECT * FROM class RIGHT JOIN student ON student.classid = class.classid;
SELECT Sname,classname,Cname,score,Tname FROM student
LEFT JOIN class ON student.classid = class.classid
RIGHT JOIN sc ON student.Sid = sc.Sid
LEFT JOIN course ON course.Cid =sc.Cid
INNER JOIN teacher ON teacher.Tid =course.Tid;
-- 找到没有班级的学生
SELECT * FROM student LEFT JOIN class ON student.classid = class.classid
WHERE class.classid IS NULL;
-- 找到没有学生的班级
SELECT * FROM class LEFT JOIN student ON student.classid = class.classid
WHERE student.sid IS NULL;
-- 没有考过试的学生
SELECT * FROM student LEFT JOIN sc on student.Sid = sc.Sid
WHERE sc.score is NULL;
(5)union 求两个查询的并集
语法:select A.field1 as f1, A.field2 as f2 from <table1> A union select B.field3 as f3, A.field4 as f4 from <table2> B;
注意:
1,列名不一致时,会以第一张表的表头为准,并对其栏目。
2,会将重复的行过滤掉。
3,如果查询的表的列数量不相等时,会报错。
4,在每个子句中的排序是没有意义的,mysql在进行合并的时候会忽略掉。
5,如果子句中的排序和limit进行结合是有意义的。
6,可以对合并后的整表进行排序。
7,union会过滤重复数据,union all不会过滤重复数据。
-- UNION 找到两个集合的并集
-- 数据类型没有关系
-- 两个结果
-- 找到没有学生的班级和没有班级的学生
SELECT * FROM student LEFT JOIN class ON student.classid = class.classid
WHERE class.classid IS NULL
UNION
SELECT * FROM class LEFT JOIN student ON student.classid = class.classid
WHERE student.sid IS NULL;
SELECT * FROM student RIGHT JOIN class ON student.classid = class.classid
UNION
SELECT * FROM class RIGHT JOIN student ON student.classid = class.classid;
-- 获取所有班级和所学生的信息
-- union 去除重复的数据
-- 添加 all 不再去除重复,全部显示
select * from student left join class
on student.classid = class.classid
union all
select * from student right join class
on student.classid = class.classid
2,子查询 内部查询
(1)where 型
# 子查询
-- 所有的子查询必须要用小括号括起来
-- where 子查询
-- 查询 id 最大的一个学生(排序,分页)
SELECT * FROM student ORDER BY Sid DESC LIMIT 1;
-- max 最大的id
SELECT * FROM student WHERE Sid = (SELECT MAX(Sid) FROM student);
-- 学过张三老师课程的学生
SELECT * FROM student WHERE Sid IN (SELECT Sid FROM sc WHERE cid = (SELECT cid FROM course WHERE Tid = (SELECT Tid FROM teacher WHERE tname = '张三' )));
-- 没有学过张三老师课程的学生
SELECT * FROM student WHERE Sid NOT IN (SELECT Sid FROM sc WHERE cid = (SELECT cid FROM course WHERE Tid = (SELECT Tid FROM teacher WHERE tname = '张三' )));
-- 查询,每个班id最大的学生(使用where子查询实现)
SELECT * FROM student,class WHERE student.classid = class.classid AND Sid IN (SELECT MAX(Sid) FROM student GROUP BY classid);
SELECT * FROM student LEFT JOIN class ON student.classid = class.classid WHERE Sid IN (SELECT MAX(Sid) FROM student GROUP BY classid);
-- 查询大于等于2人的班级名称和人数
SELECT classname,COUNT(Sid) FROM class LEFT JOIN student ON student.classid = class.classid GROUP BY class.classid HAVING COUNT(sid) >= 2;
(2)from型 把内层的查询结果当成临时表,供外层sql再次查询。
-- FROM 子查询
-- 查询大于等于5人的班级名称和人数
SELECT classname,COUNT(Sid) FROM class LEFT JOIN student ON student.classid = class.classid GROUP BY class.classid HAVING COUNT(sid) >= 2;
-- FROM 子查询 查询大于等于5人的班级名称和人数
-- FROM 子查询 要给子查询起一个表名
SELECT classname,人数 FROM class INNER JOIN
(SELECT classid,COUNT(*) 人数 FROM student GROUP BY classid ) t1 ON class.classid = t1.classid
WHERE 人数 >= 4;
-- FROM 子查询
-- 每个班级的考试次数和平均分
-- 班级名称 考试次数,平均分
SELECT * FROM class LEFT JOIN (SELECT classid,COUNT(sc.sid),AVG(score) FROM student LEFT JOIN sc ON student.Sid = sc.Sid GROUP BY classid) t1 ON class.classid = t1.classid;
SELECT classname 班级,COUNT(sc.Sid) 考试次数,AVG(score) 平均分 FROM student,sc,class WHERE student.classid = class.classid AND student.Sid = sc.Sid GROUP BY class.classid;
(3)exists型 把外层sql的结果,拿到内层sql去测试,如果内层的sql成立,则该行取出。内层查询是exists后的查询。
-- EXISTS 子查询
SELECT * FROM teacher WHERE EXISTS (SELECT * FROM student WHERE Ssex = '男');
(4)any,some,all
-- ANY SOME ALL 子查询
-- 查询出一班成绩比二班最低成绩高的学生
SELECT DISTINCT student.* FROM student INNER JOIN sc ON student.Sid = sc.Sid
WHERE classid = 1 AND score > ANY (SELECT score FROM student INNER JOIN sc ON student.Sid = sc.Sid WHERE classid = 2);
SELECT DISTINCT student.* FROM student INNER JOIN sc ON student.Sid = sc.Sid
WHERE classid = 1 AND score > SOME (SELECT score FROM student INNER JOIN sc ON student.Sid = sc.Sid WHERE classid = 2);
-- ALL 子查询
-- 查询
SELECT DISTINCT student.* FROM student INNER JOIN sc ON student.Sid = sc.Sid
WHERE classid = 1 AND score > ALL (SELECT score FROM student INNER JOIN sc ON student.Sid = sc.Sid
WHERE classid = 2);
3,流程控制函数
(1)if(expr1,expr2,expr3) 如果expr1 条件成立,则执行expr2,如果条件不成立,则执行expr3
-- IF(expr1,expr2,expr3)
-- expr1 条件
-- expr2 条件成立的结果
-- expr3 条件不成立的结果
SELECT tid,tname,IF(tsex = '1','男','女') 性别,tbirthday
FROM teacher;
(2)ifnull(expr1,expr2) 如果expr1不为Null,则执行expr1,如果expr1为Null,则执行expr2
-- IFNULL (expr1,expr2)
-- expr1 字段名
-- expr2 默认值
SELECT sid,sname,IFNULL(birthday,'2000-2-2') FROM student;
(3)case when then end
①简单case函数
语法:case 字段名 when 常量 then 结果 end;
-- 简单case
-- CASE 字段名 WHEN 常量 THEN 结果 END;
SELECT Tid,tname,CASE tsex WHEN 1 THEN '男' WHEN 0 THEN '女' ELSE '未知' END,temail,tmoney FROM teacher;
②搜素case函数
语法:case when 条件 then 结果 end;
-- 搜素case 常用
-- CASE WHEN 条件 THEN 结果 END
SELECT tid,tname,CASE WHEN tsex = 1 THEN '男' WHEN Tsex <> 1 THEN '女' END,temail,tmoney FROM teacher;
-- 查询学生的成绩,并将大于90分的用A显示,大于80分的用B显示,大于70分的用C显示,大于60分的用D显示,小于60分的显示不及格
SELECT student.Sid,Sname,birthday,Ssex,classid, CASE
WHEN score >= 90 AND score <= 100 THEN 'A'
WHEN score >= 80 AND score < 90 THEN 'B'
WHEN score >= 70 AND score < 80 THEN 'C'
WHEN score >= 60 AND score < 70 THEN 'D'
WHEN score < 60 THEN '不及格' END 成绩
FROM student INNER JOIN sc ON student.Sid = sc.Sid ;