[MySQL]复杂查询(进阶)


专栏简介 :MySql数据库从入门到进阶.

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

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

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

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


目录

1.新增

2. 聚合查询

2.1 聚合函数

3. 分组查询(grop by)

4. having 

5. 联合查询

5.1 内连接

5.2 外连接

5.3 自连接

6. 子查询

7. 合并查询


1.新增

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

语法:

insert into 表1 select * from 表2;

 示例:

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

mysql> insert into student1 select * from student2;

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

mysql> 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操作.

MySQL语句执行顺序: 

示例:

显示平均工资高于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 score;

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 score(score 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 score(score,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 课程名称,score.score from student,course,score where student.id = score.student_id and score.course_id = course.id;


5.2 外连接

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

语法:

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

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

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

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

示例:

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

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

5.3 自连接

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

语法:

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

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

示例:

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

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

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

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

 最后添加条件完成比较.

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

6. 子查询

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

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

示例:

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

--分步骤
mysql> select * from student where name = "老六";
+----+-------+------+---------------+------------+
| id | sn    | name | qq_mail       | classes_id |
+----+-------+------+---------------+------------+
|  4 | 00031 | 老六 | xuxian@qq.com |          1 |
+----+-------+------+---------------+------------+


mysql> 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 |
+----+-------+------------------+-----------------+------------+

--子查询一步完成
mysql> 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 关键字

--分步骤查询
mysql> select * from course where name = "语文" or name = "英语";
+----+------+
| id | name |
+----+------+
|  4 | 语文 |
|  6 | 英语 |
+----+------+

mysql> select * from score where course_id = 4 or course_id = 6;
+-------+------------+-----------+
| score | student_id | course_id |
+-------+------------+-----------+
|  98.0 |          1 |         6 |
|  72.0 |          4 |         6 |
|  43.0 |          6 |         4 |
|  79.0 |          6 |         6 |
|  92.0 |          7 |         6 |
+-------+------------+-----------+

--多行子查询
mysql> select * from score where course_id in (select id from course where name = "语文" or name = "英语");
+-------+------------+-----------+
| score | 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 或者名字为"英文"的课程

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

示例:

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

mysql> 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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


在正式开始之前,我们先来看下 MySQL 服务器的配置和版本号信息,如下图所示: “兵马未动粮草先行”,看完了相关的配置之后,我们先来创建一张测试表和一些测试数据。 -- 如果存在 person 表先删除 DROP TABLE IF EXISTS person; -- 创建 person 表,其中
&gt; [合辑地址:MySQL全面瓦解](https://www.cnblogs.com/wzh2010/category/1859594.html &quot;合辑地址:MySQL全面瓦解&quot;) # 1 为什么需要数据库备份 - 灾难恢复:当发生数据灾难的时候,需要对损坏的数据进行恢复和
物理服务机的CPU、内存、存储设备、连接数等资源有限,某个时段大量连接同时执行操作,会导致数据库在处理上遇到性能瓶颈。为了解决这个问题,行业先驱门充分发扬了分而治之的思想,对大库表进行分割,&#xA;然后实施更好的控制和管理,同时使用多台机器的CPU、内存、存储,提供更好的性能。而分治有两种实现方式:垂直拆
1 回顾 上一节我们详细讲解了如何对数据库进行分区操作,包括了 垂直拆分(Scale Up 纵向扩展)和&#160;水平拆分(Scale Out 横向扩展) ,同时简要整理了水平分区的几种策略,现在来回顾一下。 2 水平分区的5种策略 2.1 Hash(哈希) 这种策略是通过对表的一个或多个列的Ha
navicat查看某个表的所有字段的详细信息 navicat设计表只能一次查看一个字段的备注信息,那怎么才能做到一次性查询表的信息呢?SELECT COLUMN_NAME,COLUMN_COMMENT,COLUMN_TYPE,COLUMN_KEY FROM information_schema.CO
文章浏览阅读4.3k次。转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52768613前言:数据库每天的数据不断增多,自动删除机制总体风险太大,想保留更多历史性的数据供查询,于是从小的hbase换到大的hbase上,势在必行。今天记录下这次数据仓库迁移。看下Agenda:彻底卸载MySQL安装MySQL_linux服务器进行数据迁移
文章浏览阅读488次。恢复步骤概要备份frm、ibd文件如果mysql版本发生变化,安装回原本的mysql版本创建和原本库名一致新库,字符集都要保持一样通过frm获取到原先的表结构,通过的得到的表结构创建一个和原先结构一样的空表。使用“ALTER TABLE DISCARD TABLESPACE;”命令卸载掉表空间将原先的ibd拷贝到mysql的仓库下添加用户权限 “chown . .ibd”,如果是操作和mysql的使用权限一致可以跳过通过“ALTER TABLE IMPORT TABLESPACE;”命令恢_alter table discard tablespace
文章浏览阅读225次。当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化:单表优化除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑、部署、运维的各种复杂度,一般以整型值为主的表在千万级以下,字符串为主的表在五百万以下是没有太大问题的。而事实上很多时候MySQL单表的性能依然有不少优化空间,甚至能正常支撑千万级以上的数据量:字段尽量使用TINYINT、SMALLINT、MEDIUM_INT作为整数类型而非INT,如果非负则加上UNSIGNEDVARCHAR的长度只分配_开发项目 浏览记录表 过大怎么办
文章浏览阅读1.5k次。Mysql创建、删除用户MySql中添加用户,新建数据库,用户授权,删除用户,修改密码(注意每行后边都跟个;表示一个命令语句结束):1.新建用户登录MYSQL:@>mysql -u root -p@>密码创建用户:mysql> insert into mysql.user(Host,User,Password) values("localhost_删除mysql用户组
MySQL是一种开源的关系型数据库管理系统,被广泛应用于各类应用程序的开发中。对于MySQL中的字段,我们需要进行数据类型以及默认值的设置,这对于数据的存储和使用至关重要。其中,有一个非常重要的概念就是MySQL字段默认字符串。 CREATE TABLE `my_...
MySQL是一个流行的开源关系型数据库管理系统,广泛应用于Web应用程序开发、数据存储和管理。在使用MySQL时,正确设置字符集非常重要,以确保数据的正确性和可靠性。 在MySQL中,字符集表示为一系列字符和字母的集合。MySQL支持多种字符集,包括ASCII、UTF...
MySQL存储函数 n以内偶数 MySQL存储函数能够帮助用户简化操作,提高效率,常常被用于计算和处理数据。下面我们就来了解一下如何使用MySQL存储函数计算n以内的偶数。 定义存储函数 首先,我们需要定义一个MySQL存储函数,以计算n以内的偶数。下...
MySQL是一个流行的关系型数据库管理系统,基于客户机-服务器模式,可在各种操作系统上运行。 MySQL支持多种字符集,不同的字符集包括不同的字符,如字母、数字、符号等,并提供不同的排序规则,以满足不同语言环境的需求。 //查看MySQL支持的字符集与校对规...
在MySQL数据库中,我们有时需要对特定的字符串进行截取并进行分组统计。这种操作对于数据分析和报表制作有着重要的应用。下面我们将讲解一些基本的字符串截取和分组统计的方法。 首先,我们可以使用substring函数对字段中的字符串进行截取。假设我们有一张表stude...
MySQL提供了多种字符串的查找函数。下面我们就一一介绍。 1. LIKE函数 SELECT * FROM mytable WHERE mycolumn LIKE 'apple%'; 其中"apple%"表示以apple开头的字符串,%表示任意多个字符...
MySQL 是一种关系型数据库管理系统,广泛应用于各种不同规模和类型的应用程序中。在 MySQL 中,处理字符串数据是很常见的任务。有时候,我们需要在字符串的开头添加一定数量的 0 ,以达到一定的位数。比如,我们可能需要将一个数字转换为 4 位或 5 位的字符串,不足的...
MySQL是一种流行的关系型数据库管理系统,支持多种数据类型。以下是MySQL所支持的数据类型: 1. 数值型数据类型: - TINYINT 保存-128到127范围内的整数 - SMALLINT 保存-32768到32767范围内的整数 - MEDIU...
MySQL中存储Emoji表情字段类型 在现代互联网生态中,表情符号已经成为人们展示情感和思想的重要方式之一,因此将表情符号存储到数据库中是一个经常出现的问题。MySQL作为最流行的开源关系型数据库管理系统之一,也需要能够存储和管理这些表情符号的字段类型。 UT...
MySQL是一种关系型数据库管理系统。在MySQL数据库中,有多种不同的数据类型。而其中,最常见的数据类型之一就是字符串类型。在MySQL中,字符串类型的数据通常会被存储为TEXT或VARCHAR类型。 首先,让我们来看一下VARCHAR类型。VARCHAR是My...
MySQL字符串取整知识详解 MySQL是一种开源的关系型数据库管理系统,广泛应用于各个领域。在使用MySQL过程当中,我们经常需要对数据进行取整操作。本文将介绍如何使用MySQL字符串取整来处理数据取整问题。 什么是MySQL字符串取整? MySQL...