多表查询的两种方式
方式1:连表操作
| inner join on 内连接 |
| select * from emp inner join dep on emp.dep_id=dep.id; |
| 只连接两张表中公有的数据部分 |
| |
| left join 左连接 |
| select * from emp left join dep on emp.dep_id=dep.id; |
| 以左表为基准 展示左表所有的数据 如果没有对应项则用NULL填充 |
| |
| |
| right join 右连接 |
| select * from emp right join dep on emp.dep_id=dep.id; |
| 以右表为基准 展示右表所有的数据 如果没有对应项则用NULL填充 |
| |
| |
| union 全连接 |
| select * from emp left join dep on emp.dep_id=dep.id |
| union |
| select * from emp right join dep on emp.dep_id=dep.id; |
| |
| 以左右表为基准 展示所有的数据 各自没有的全部NULL填充 |
| ''' |
| 学会了连接操作之后也可以连接N多张表 |
| 思路:将拼接之后的表起别路当成一张表再去与其他表拼接 |
| 再起别名当一张表 再去与其他表拼接 其次往复即可 |
| ''' |
方式2:子查询
| 将一条SQL语句用括号括起来当成另外一条SQL语句的查询条件 |
| |
| 题目:求姓名是jason的员工部门名称 |
| 子查询类似于我们日常生活中解决问题的方式>>>:分布操作 |
| 步骤1:先根据jason获取部门编号 |
| select dep_id from emp where name='jason'; |
| 步骤2:再根据部门编号获取部门名称 |
| select name from dep where id=200; |
| 总结 |
| select name from dep where id=(select name dep_id from emp where name='jason'); |
| ''' |
| 很多时候多表查询需要结合实际情况判断用哪种 更多时候甚至是相互配合使用 |
| ''' |
小知识点补充说明
concat和concat_ws的区别
| 1.concat与concat_ws |
| concat用于分组之前的字段拼接操作 |
| select concat(name, '$',sex) from emp; |
| concat_ws拼接多个字段并且中间的连接符一致 |
| select concat_ws('|',name,sex,age,dep_id) from emp; |
exists
| sql1 exists sql2 |
| sql2有结果的情况下才会执行sql1 否则不执行sql1 返回空数据 |
表相关操作
| altet table 表名 rename 新表名 |
| |
| alter table 表名 add 字段名 字段类型(数字) 约束条件; |
| alter table 表名 add 字段名 字段类型(数字) 约束条件 after 已有字段; |
| |
| alter table 表名 add 字段名 字段类型(数字) 约束条件 first; |
| |
| alter table 表名 change 旧字段名 字段类型(数字) 约束条件; |
| |
| alter table 表名 modify 字段名 新字段类型(数字) 约束条件; |
| |
| alter table 表名 drop 字段名; |
可视化软件Navicat
| 第三方开发的用来充当数据库客户端的简单快捷的操作界面 |
| 无论第三方软件有多么的花里胡哨 底层的本质还是SQL |
| 能够操作数据库的第三方可视化软件有很多 其中针对MySQL最出名的就是Navicat |
| |
| 1.浏览器搜索Navicat直接下载 |
| 版本很多、能够充当的数据库客户端也很多 |
| 2.破解方式 |
| 先试用在破解、直接下载破解版(老版本)、修改试用日期 |
| 3.常用操作 |
| 有些功能可能需要自己修改SQL预览 |
| 创建库、表、记录、外键 |
| 逆向数据库到模型、模型创建 |
| 新建查询可以编写SQL语句并自带提示功能 |
| SQL语句注释语法 |
| --、 |
| 运行、转储SQL文件 |
多表查询练习题
| """ |
| 编写复杂的SQL不要想着一口气写完 |
| 一定要先明确思路 然后一步步写一步步查一步步补 |
| """ |
| 1、查询所有的课程的名称以及对应的任课老师姓名 |
| 4、查询平均成绩大于八十分的同学的姓名和平均成绩 |
| 7、查询没有报李平老师课的学生姓名 |
| 8、查询没有同时选修物理课程和体育课程的学生姓名 |
| 9、查询挂科超过两门(包括两门)的学生姓名和班级 |
| |
| -- 1、查询所有的课程的名称以及对应的任课老师姓名 |
| |
| |
| -- select * from course; |
| -- select * from teacher; |
| |
| -- SELECT |
| -- teacher.tname, |
| -- course.cname |
| -- FROM |
| -- course |
| -- INNER JOIN teacher ON course.teacher_id = teacher.tid; |
| -- 4、查询平均成绩大于八十分的同学的姓名和平均成绩 |
| |
| |
| -- select * from student; |
| -- select * from score; |
| |
| |
| -- select student_id,avg(num) as avg_num from score group by student_id having avg_num>80; |
| |
| -- SELECT |
| -- student.sname, |
| -- t1.avg_num |
| -- FROM |
| -- student |
| -- INNER JOIN ( |
| -- SELECT |
| -- student_id, |
| -- avg(num) AS avg_num |
| -- FROM |
| -- score |
| -- GROUP BY |
| -- student_id |
| -- HAVING |
| -- avg_num > 80 |
| -- ) AS t1 ON student.sid = t1.student_id; |
| -- 7、查询没有报李平老师课的学生姓名 |
| |
| |
| |
| |
| -- select tid from teacher where tname = '李平老师'; |
| -- select cid from course where teacher_id = (select tid from teacher where tname = '李平老师'); |
| |
| -- select distinct student_id from score where course_id in (select cid from course where teacher_id = (select tid from teacher where tname = '李平老师')) |
| |
| -- SELECT |
| -- sname |
| -- FROM |
| -- student |
| -- WHERE |
| -- sid NOT IN ( |
| -- SELECT DISTINCT |
| -- student_id |
| -- FROM |
| -- score |
| -- WHERE |
| -- course_id IN ( |
| -- SELECT |
| -- cid |
| -- FROM |
| -- course |
| -- WHERE |
| -- teacher_id = ( |
| -- SELECT |
| -- tid |
| -- FROM |
| -- teacher |
| -- WHERE |
| -- tname = '李平老师' |
| -- ) |
| -- ) |
| -- ) |
| -- 8、查询没有同时选修物理课程和体育课程的学生姓名(报了两门或者一门不报的都不算) |
| |
| |
| |
| |
| -- select cid from course where cname in ('物理','体育'); |
| |
| -- select * from score where course_id in (select cid from course where cname in ('物理','体育')) |
| |
| -- select student_id from score where course_id in (select cid from course where cname in ('物理','体育')) |
| -- group by student_id |
| -- having count(course_id) = 1; |
| |
| -- SELECT |
| -- sname |
| -- FROM |
| -- student |
| -- WHERE |
| -- sid IN ( |
| -- SELECT |
| -- student_id |
| -- FROM |
| -- score |
| -- WHERE |
| -- course_id IN ( |
| -- SELECT |
| -- cid |
| -- FROM |
| -- course |
| -- WHERE |
| -- cname IN ('物理', '体育') |
| -- ) |
| -- GROUP BY |
| -- student_id |
| -- HAVING |
| -- count(course_id) = 1 |
| -- ) |
| -- 9、查询挂科超过两门(包括两门)的学生姓名和班级 |
| |
| |
| -- select * from class |
| |
| |
| -- select * from score where num < 60; |
| |
| -- select student_id,count(course_id) from score where num < 60 group by student_id; |
| |
| -- select student_id from score where num < 60 group by student_id having count(course_id) >= 2; |
| |
| SELECT |
| student.sname, |
| class.caption |
| FROM |
| student |
| INNER JOIN class ON student.class_id = class.cid |
| WHERE |
| student.sid IN ( |
| SELECT |
| student_id |
| FROM |
| score |
| WHERE |
| num < 60 |
| GROUP BY |
| student_id |
| HAVING |
| count(course_id) >= 2 |
| ); |
python操作MySQL
| pymysql模块 |
| pip3 install pymysql |
| |
| |
| import pymysql |
| |
| |
| conn = pymysql.connect( |
| host='127.0.0.1', |
| port=3306, |
| user='root', |
| password='123', |
| db='db4_03', |
| charset='utf8mb4' |
| ) |
| |
| |
| cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) |
| |
| |
| sql = 'select * from score;' |
| |
| affect_rows = cursor.execute(sql) |
| print(affect_rows) |
| |
| res = cursor.fetchall() |
| print(res) |
pymysql补充说明
| 1.获取数据 |
| fetchall() 获取所有的结果 |
| fetchone() 获取结果集的第一个数据 |
| fetchmany() 获取指定数量的结果集 |
| ps:注意三者都有类似于文件光标移动的特性 |
| |
| cursor.scroll(1,'relatvie') |
| cursor.scroll(0,'absolute') |
| |
| 2.增删改查 |
| autocommit=True |
| conn.commit() |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构