主页>技术社区>IT 技术>数据库>MySQL>MySQL教程

[MySQL]复杂查询(进阶)

eIT.com.cn 2022/11/23 9:22:28 阅读 53 次

打印



专栏简介 :从入门到进阶.

题目来源:leetcode,牛客,剑指offer.

创作目标:记录学习学习历程

希望在提升自己的同时,帮助他人,与大家一起共同进步,互相成长.

学历代表过去,能力代表现在,学习能力代表未来! 


目录


1.新增

将结果作为values,插入到指定表中.

语法:

insert into 表1 select * from 表2;

 示例:

将学生表1中的数据插入到学生表2中.

> insert into student1 select * from student2;> select * from student1;+------+------+| id   | name |+------+------+|1 | 张三 ||2 | 李四 ||3 | 王五 ||4 | 老六 |+------+------+4 rows in set (0.00 sec)> select * from student2;+------+------+| id   | name |+------+------+|1 | 张三 ||2 | 李四 ||3 | 王五 ||4 | 老六 |+------+------+4 rows in set (0.00 sec)

Tips:

  • 与插入表的列数和类型要匹配.
  • 所有select都可以和该操作组合使用.

2. 聚合

之前提到的条件都是基于列和列之,而聚合针对某个列中所有的行来运算.

2.1 聚合

说明
count返回到的数据的
sum返回到数据的总和 (不是数字没有意义)
avg返回到数据的平均值 (不是数字没有意义)
max返回到数据的最大值 (不是数字没有意义)
min返回到数据的最小值 (不是数字没有意义)
  • count

语法:

select count(表达式) from 表名;
  • Tips: count(*)包含null所在的行. 

示例: 

班级有多少学生


  • sum

语法:

select sum(表达式) from 表名

示例:

数学总分


  • avg

语法:

select avg(表达式) from student;

示例:

平均总分


  • max

语法:

select max(表达式) from 表名;

示例:

返回英语最高分


  • min

语法:

select min(表达式) from 表名;

示例:

返回大于60分以上的数学最低分


3. 分组(grop by)

语法:

select 字段 from 表名 group by 字段

示例:

  • 单个字段分组

查出学生等级的种类:(按等级划分,重复的)

select grade from student group by grade; 


  • 多个字段分组

按名字和等级划分重复的同学:

select name from student group by name,grade;

Tip:此时将名字和等级看做是整体,只有名字和等级都相同的才能分成一组,其中不同就不是一组. 


  • 搭配聚合分组

查看表中相同人名的个数:

select name,count(*) from student group by name;


4. having 

wherehaving都是设定筛选条件的语句,有相似点也有不同点.

  • group by子句进行分组以后,分组之前筛选用where,分组之后筛选用having.
  • having必须和group by 一起使用.
  • where之后不能使用聚合,having之后可以使用聚合.
  • having可以看做是对where的补充,where筛选出合适的数据having才能进行聚合操作.
字名作用
where 子句

1)对结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据.

2)where 后面不可以使用聚合

3)过滤

having 子句

1)having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,.

2)having 后面可以使用聚合

3)过滤

4)所有的where操作.

语句执行顺序: 

示例:

平均工资高于1500的人的平均工资.

select name,avg(salary) from student group by name having avg(salary)>1500;


5. 联合

实际开发中数据往往来自不同的表,所以需要多表联合,多表联合本质是对多张表的数据取笛卡尔积(也就是全排列).列数是两个表列数之和,行数是两个表行数之和.因此其中只有一部分数据是有效的,需要后续相关操作进行筛选.

 Tips:关联表时可以对关联表使用别名,更加直观.

筛选前: 

 筛选后:

 Tips:如果两张表中字段重名,不加成员访问修饰符" . ",会报错 ambigous(模糊不清的)

 为了使数据更加直观明了,本文提供以下供后续案例使用.

drop table if exists classes;drop table if exists student;drop table if exists course;drop table if exists ;create table classes (id int primary key auto_increment,name varchar(20),`desc` varchar(100));create table student (id int primary key auto_increment,sn varchar(20),qq_mail varchar(20),classes_id int);create table course(id int primary key auto_increment,name varchar(20));create table ( decimal(3,1),student_id int,course_id int);insert into classes(name,`desc`) values ('计算机系2019级1班','学习了计算机原理、C和Java语言、数据结构和算法'),('系2019级3班','学习了中国传统文学'),('化2019级5班','学习了机械化');insert into student(sn,name,qq_mail,classes_id) values('09982','张三','zhangsan@qq.com',('00835','李四',null,('00391','王五',('00031','老六','xuxian@qq.com',('00054','老师我作业忘带了',('51234','芝士雪豹','xuebao@qq.com',2),('83223','tellme',('09527','老外学英文','foreigner@qq.com',2);insert into course(name) values('Java'),('中国传统文化'),('计算机原理'),('语文'),('高等数学'),('英语');insert into (,student_id,course_id) values-- 张三(70.5,1,(98.5,3),(33,5),(98,6),-- 李四(60,2,(59.5,-- 王五(33,3,(68,(99,-- 老六(67,4,(23,(56,(72,-- 老师我作业忘带了(81,5,(37,-- 芝士雪豹(56,6,(43,4),(79,-- 老外学英文(80,7,(92,6);

5.1 内连接

内连接就是指结果仅包含符合连接条件的行,参与连接的两个表都应符合连接条件.

语法:

1.from多个表简单明了,但只能实现内连接不能实现外连接.

select * from 表1,表2...;

2.join on可以既可以实现内连接也可以实现外连接. 

select * from 表1 join 表2 on...;
select * from 表1 inner join 表2 on...;

示例:

老六同学的全科成绩.

步骤:

  1. 分析需要联合的表(学生表和分数表),然后计算笛卡尔积.
  2. 合法性筛选(分数表id对应学生id).
  3. 根据需求加入必要条件.xue
  4. 去要的列.

 1.计算学生表和分数表的笛卡尔积.(160多行数据,大部分无效)

 2.分数表中id对应学生表中id

 3.学生姓名为老六

 4.不必要的列


所有同学的成绩,及同学的个人信息.(学生表,课程表,分数表)

select student.name as 姓名,course.name as 课程,. from student,course, where student.id = .student_id and .course_id = course.id;


5.2 外连接

连接结果不仅包含符合连接条件的行,同时也包含不符合连接条件的行,分为左外连接和右外连接.

语法:

左外连接:左表有多少数据就多少数据,右边没有的就用null表示

select * from 表1 left join 表2 on 连接条件;

右外连接:右表有多少数据就多少数据,左表没有的就用null表示

select * from 表1 right join 表2 on 条件;

示例:

假如王五同学转专业,数据表还未同步他的成绩信息.

> select * from student;+------+------+| id   | name |+------+------+|1 | 张三 ||2 | 李四 ||3 | 王五 |+------+------+> select * from ;+------------+-------+| student_id |  |+------------+-------+|  1 |90 ||  2 |89 ||  4 |77 |+------------+-------+--左外连接> select * from student left join  on student.id = .student_id;+------+------+------------+-------+| id   | name | student_id |  |+------+------+------------+-------+|1 | 张三 |  1 |90 ||2 | 李四 |  2 |89 ||3 | 王五 |   NULL |  NULL |+------+------+------------+-------+--右外连接> select * from student right join  on student.id = .student_id;+------+------+------------+-------+| id   | name | student_id |  |+------+------+------------+-------+|1 | 张三 |  1 |90 ||2 | 李四 |  2 |89 || NULL | NULL |  4 |77 |+------+------+------------+-------+

5.3 自连接

自连接顾名思义就是自己和自己笛卡尔积,自连接的就是把行转成列.不管和where子句还是having子句都是针对不同列之行进行操作,如果只有列并且想要行与行之间进行比较,就必须自连接.

语法:

select * from 表名 as 别名1,表名 as 别名2;

Tips:自连接必须给表起个别名,否则两个相同的表连接会报错. 

示例:

java成绩高于计算机原理成绩的同学.

由图可以看出,java成绩和计算机原理成绩之比较在同一列,所以需要行转列.

 自连接之后可以发现,可以进行列与列之比较了,本题针对的是同一同学不同课程,所以筛选条件是两表的学生id相同.

> select * from  as s1, as s2 where s1.student_id = s2.student_id;

 最后条件完成比较.

> select * from  as s1, as s2 where s1.student_id = s2.student_id and s1.course_id = 3 and s2.course_id = 1 and s1.>s2.;+-------+------------+-----------+-------+------------+-----------+|  | student_id | course_id |  | student_id | course_id |+-------+------------+-----------+-------+------------+-----------+|  98.5 |  1 | 3 |  70.5 |  1 | 1 ||  68.0 |  3 | 3 |  33.0 |  3 | 1 |+-------+------------+-----------+-------+------------+-----------+

6. 子

子是指嵌套在其他语句中的select语句,也叫嵌套.(本质上就是套娃)

  • 单行子:返回一行记录的子

示例:

返回与"老六"同学同班的同学.

--分步骤> select * from student where name = "老六";+----+-------+------+---------------+------------+| id | sn| name | qq_mail   | classes_id |+----+-------+------+---------------+------------+|  4 | 00031 | 老六 | xuxian@qq.com |  1 |+----+-------+------+---------------+------------+> select * from student where classes_id = 1 and name!="老六";+----+-------+------------------+-----------------+------------+| id | sn| name | qq_mail | classes_id |+----+-------+------------------+-----------------+------------+|  1 | 09982 | 张三 | zhangsan@qq.com |  1 ||  2 | 00835 | 李四 | NULL|  1 ||  3 | 00391 | 王五 | NULL|  1 ||  5 | 00054 | 老师我作业忘带了 | NULL|  1 |+----+-------+------------------+-----------------+------------+--子一步完成> select * from student where classes_id = (select classes_id from student where name = "老六" ) and name!="老六";+----+-------+------------------+-----------------+------------+| id | sn| name | qq_mail | classes_id |+----+-------+------------------+-----------------+------------+|  1 | 09982 | 张三 | zhangsan@qq.com |  1 ||  2 | 00835 | 李四 | NULL|  1 ||  3 | 00391 | 王五 | NULL|  1 ||  5 | 00054 | 老师我作业忘带了 | NULL|  1 |+----+-------+------------------+-----------------+------------+

  • 多行子:返回多行记录的子

示例:

语文或英语课程的成绩信息.

1. (not) in 关键字

--分步骤> select * from course where name = "语文" or name = "英语";+----+------+| id | name |+----+------+|  4 | 语文 ||  6 | 英语 |+----+------+> select * from  where course_id = 4 or course_id = 6;+-------+------------+-----------+|  | student_id | course_id |+-------+------------+-----------+|  98.0 |  1 | 6 ||  72.0 |  4 | 6 ||  43.0 |  6 | 4 ||  79.0 |  6 | 6 ||  92.0 |  7 | 6 |+-------+------------+-----------+--多行子> select * from  where course_id in (select id from course where name = "语文" or name = "英语");+-------+------------+-----------+|  | student_id | course_id |+-------+------------+-----------+|  98.0 |  1 | 6 ||  72.0 |  4 | 6 ||  43.0 |  6 | 4 ||  79.0 |  6 | 6 ||  92.0 |  7 | 6 |+-------+------------+-----------+

2. (not) exists 关键字

由于 in 关键字结果在内存中,如果内存中存不下可以考虑使用exists关键字,但exists关键字执行效率低下,且可读性差.不如分步.


 

7. 合并

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all,使用union和union all时,前后结果集中,字段要一致.

Tips:

  • union结果会去重,union all 可以保留多份.
  • or 只能联合表中的结果,union 可以联合多个表中的.
  • union

示例:

id<3 或者名字为"英文"的课程

> select * from course where id<3 union select * from course where name = "英语";+----+--------------+| id | name |+----+--------------+|  1 | Java ||  2 | 中国传统文化 ||  6 | 英语 |+----+--------------+
  • union all

示例:

id<3 或者名字为"java"的课程

> select * from course where id<3 union all select * from course where name = "Java";+----+--------------+| id | name |+----+--------------+|  1 | Java ||  2 | 中国传统文化 ||  1 | Java |+----+--------------+

总结

以上是为你收集整理的全部内容,希望文章能够帮你解决所遇到的程序开发问题。

原文地址:https://blog.csdn.net/liu_xuixui






相关内容

• MySQL的索引与事务 (2022/12/6 7:56:56)
• 【MySQL】MVCC原理分析 + 源码解读 -- 必须说透 (2022/12/6 7:56:55)
• CDH大数据平台 29Cloudera Manager Console之superset之MySQL元数据配置(markdown新版三) (2022/11/29 12:05:25)
• mysql 锁机制与原理详解 (2022/11/28 16:05:02)
• [MSSQL]汉字转拼音函数实现语句 (2022/11/26 6:11:29)
• 采用 Kettle 分页处理大数据量抽取任务 (2022/11/24 14:52:15)
• Oracle Flashback 和 RMAN 示例 (2022/11/24 14:52:15)
• MySQL 的安装和配置 (2022/11/24 14:52:15)
• NFT是什么?一篇文章搞懂NFT的概念 (2022/11/23 18:08:16)
• [MySQL]复杂查询(进阶) (2022/11/23 9:22:28)



热门栏目


特别声明


最新资讯
热讯排行



合作媒体友情链接
生活常识小贴士 软件开发教程 智慧城市生活网 息县通生活服务[移动版] 息县商圈[移动版] 美食菜谱
健康养生 法律知识 科技频道 电影影讯 留学考研学习 星座生肖|解梦说梦




关于我们 | 联系我们 | 合作媒体 | 使用条款 | 隐私权声明 | 版权声明

      Copyright © 2023 eIT.com.cn. All Rights Reserved. 豫ICP备2022012332号