当前位置:网站首页>MySQL数据库(三)高级数据查询语句

MySQL数据库(三)高级数据查询语句

2022-07-06 09:25:00 手可摘鑫晨

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 ;

原网站

版权声明
本文为[手可摘鑫晨]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_61562689/article/details/125213921