【⑦MySQL】· 一文了解四大子查询

前言

✨欢迎来到小K的MySQL专栏,本节将为大家带来MySQL标量/单行子查询、列子/表子查询的讲解

目录

      • 前言
      • 一、子查询概念
      • 二、标量/单行子查询、列子/表子查询
      • 三、总结

一、子查询概念

子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从MySQL 4.1开始引入;在特定情况下,一个查询语句的条件需要另一个查询语句来获取,内层查询(inner query)语句的查询结果,可以为外层查询(outer query)语句提供查询条件。

内层查询即子查询,外层查询即主查询,只是叫法不同而已

查询需求:

查询公司中工资最低的员工信息

工资最低是多少?

SELECT * FROM emp WHERE sal=(SELECT MIN(sal) FROM emp); 

子查询规范:

  • 子查询必须放在小括号中
  • 子查询一般放在比较操作符的右边,以增强代码可读性
  • 子查询可以出现在几乎所有的SELECT字句中(如:SELECT、FROM、WHERE、ORDER BY、HAVING子句

子查询分类:

  1. 根据子查询返回的数据分类:

    • 标量子查询(scalar subquery):返回1行1列一个值

    • 行子查询(row subquery):返回的结果集是 1 行 N 列

    • 列子查询(column subquery):返回的结果集是 N 行 1列

    • 表子查询(table subquery):返回的结果集是 N 行 N 列

      子查询可以返回一个标量(就一个值)、一个行、一个列或一个表,这些子查询分别称之为标量、行、列和表子查询。

  2. 根据子查询和主查询之间是否有条件关联分类:

    • 相关子查询:两个查询之间有一定的条件关联(相互联系)
    • 不相关子查询:两个查询之间没有条件关联(相互独立)
  3. 为了方便,对于在何处使用子查询给大家给出几点个人建议:

    • 子查询出现在WHERE子句中:此时子查询返回的结果一般都是单列单行、单行多列、多行单列
    • 子查询出现在HAVING子句中:此时子查询返回的都是单行单列数据,同时为了使用统计函数操作
    • 子查询出现在FROM子句中:此时子查询返回的结果图一般都是多行多列,可以按照一张数据表(临时表)的形式操作

二、标量/单行子查询、列子/表子查询

✨✨标量子查询

子查询返回的是单行单列的数据,就是一个值

  • 查询出基本工资比ALLEN低的全部员工信息
SELECT * FROM emp WHERE sal<(SELECT sal FROM emp WHERE eanme='ALLEN');
  • 查询基本工资高于公司平均工资的全部员工信息
SELECT * FROM emp WHERE sal>(SELECT AVG(sal) FROM emp);
  • 查询出与ALLEN从事同一工作,并且基本工资高于员工编号为7521的全部员工信息
SELECT * FROM emp WHERE job=(SELECT job FROM emp WHERE ename='ALLEN') 
AND sal>(SELECT sal FROM emp WHERE empno=7521)
#把ALLEN自己去掉
AND ename<>'ALLEN';

效果如下:

在这里插入图片描述

✨✨单行子查询

子查询返回的是单行多列的数据,就是一条记录

  • 查询与SCOTT从事统一工作且工资相同的员工信息
SELECT * FROM emp WHERE (job,sal)=(SELECT job,sal FROM emp WHERE ename='SCOTT')
AND ename<>'SCOTT';
  • 查询与员工编号为7566从事统一工作且领导相同的全部员工信息
SELECT * FROM emp WHERE (job,mgr)=(SELECT job,mgr FROM emp WHERE empno=7566)
AND emp<>7566;

效果如下:
在这里插入图片描述

✨✨列子查询(多行子查询)

子查询返回的是多行单列的数据,就是一列数据。多行子查询也称为集合比较子查询,

在使用多行子查询需要使用多行比较操作符:

操作符含义
IN等于列表中的任意一个
ANY需要和单行比较操作符一起使用(>、<、=、<>…),与子查询结果中任何一个值比较,一个成立
ALL需要和单行比较操作符一起使用(>、<、=、<>…),和子查询返回的所有值比较,同时成立
SOME实际上是ANY的别名,作用相同,一般用ANY
  • IN操作符

    IN 运算符用来判断表达式的值是否位于给出的列表中;如果是,返回值为 1,否则返回值为 0。

    NOT IN 的作用和 IN 恰好相反,NOT IN 用来判断表达式的值是否不存在于给出的列表中;如果不是,返回值为 1,否则返回值为 0。

    • 查询出与每个部门中最低工资相同的员工信息
      • 按照部门分组,统计每个部门的最低工资
      • 根据最低工资查询出员工信息
SELECT * FROM emp WHERE sal IN(SELECT MIN(sal) FROM emp GROUP BY deptno)
AND deptno IS NOT NULL;
  • ANY操作符

    ANY关键字是一个MySQL运算符,如果子查询条件中ANY的比较结果为TRUE,则它会返回布尔值TRUE

    • 查询工资比任何管理工资都要高的员工信息
      • 查找出每个管理的薪资
      • 每个员工的薪资与每个管理的薪资比较
SELECT * FROM emp WHERE sal >ANY(
SELECT MIN(sal) FROM emp WHERE job='MANAGER' GROUP BY deptno);
  • ALL操作符

    ALL关键字是一个MySQL运算符,如果子查询条件中ALL的比较结果为TRUE,则它会返回布尔值TRUE

    • 案例同ANY操作符

效果如下:

在这里插入图片描述

✨✨表子查询

子查询返回的是多行多列的数据,就是一个表格
必须使用 IN、ANY 和 ALL 操作符对子查询返回的结果进行比较

综合练习:

  • 在emp表中,得到与10号部门任何一个员工入职年份和领导相同的员工信息(用在where子句中)
    • 需要用到DATE_FORMAT(hiredate,'%Y')将入职日期转换为年份
SELECT * FROM emp
WHERE (DATE_FORMAT(hiredate,'%Y'),mgr) IN (SELECT DATE_FORMAT(hiredate,'%Y') hiryear,mgr FROM emp WHERE deptno=10);

在这里插入图片描述

  • 查询出每个部门的编号、名称、位置、部门人数、平均工资(用在from子句中)
    • 以前学的多表联合查询——-emp、dept
    • 用子查询联合查询
SELECT d.deptno,d.dname,d.loc,COUNT(e.deptno),ROUND(AVG(sal),2) FROM
dept d LEFT JOIN emp e
ON e.deptno=d.deptno
GROUP BY d.deptno,d.dname,d.loc;SELECT dept.deptno,dept.dname,dept.loc,d.count,d.avgsal FROM dept LEFT JOIN 
(SELECT deptno,COUNT(*) count,AVG(sal) avgsal  FROM emp GROUP BY deptno) d
ON dept.deptno=d.deptno;

在这里插入图片描述

  • 查询出所有在’SALES’部门工作的员工编号、姓名、基本工资、奖金、职位、雇佣日期、部门的最高和最低工资。(where和from子句同时使用)
#1
SELECT e.empno,e.ename,e.sal,e.comm,e.job,e.hiredate,minsal,maxsal,e.deptno  
FROM emp e JOIN 
(SELECT deptno,MIN(sal) minsal,MAX(sal) maxsal FROM emp GROUP BY deptno) td
ON e.deptno=td.deptno AND e.deptno=(SELECT deptno FROM dept WHERE dname='SALES');#2
SELECT e.empno,e.ename,e.sal,e.comm,e.job,e.hiredate,minsal,maxsal,e.deptno  
FROM emp e JOIN 
(SELECT deptno,MIN(sal) minsal,MAX(sal) maxsal FROM emp GROUP BY deptno
HAVING deptno=(SELECT deptno FROM dept WHERE dname='SALES')) td
ON e.deptno=td.deptno;

在这里插入图片描述

  • 查询出比‘ALLEN’或‘CLACRK’薪资多的所有员工的编号、姓名、基本工资、部门名称、领导姓名、部门人数。
#隐式方式
SELECT e.empno,e.ename,e.sal,d.dname,me.ename 领导,temp.count FROM emp e,dept d,emp me,
(SELECT deptno,COUNT(deptno) count FROM emp e GROUP BY deptno) temp
WHERE e.deptno=d.deptno AND e.mgr=me.empno AND temp.deptno=e.deptno
AND e.sal >ANY(SELECT sal FROM emp WHERE ename IN('ALLEN','CLARK'))
AND e.ename NOT IN('ALLEN','CLARK');#显示方式
SELECT e.empno,e.ename,e.sal,d.dname,me.ename 领导,temp.count 
FROM emp e 
JOIN dept d ON e.deptno=d.deptno
LEFT JOIN emp me ON e.mgr=me.empno
JOIN (SELECT deptno,COUNT(deptno) count FROM emp e GROUP BY deptno) temp ON temp.deptno=e.deptno
AND e.sal >ANY(SELECT sal FROM emp WHERE ename IN('ALLEN','CLARK'))
AND e.ename NOT IN('ALLEN','CLARK');

在这里插入图片描述

  • 列出公司各个部门的经理(假设每个部门只有一个经理,job为‘MANAGER’)的姓名、薪资、部门名称、部门人数、部门平均工资。
#隐式方式
SELECT e.ename,e.sal,d.dname,temp.count,temp.avgsal
FROM emp e,dept d,(SELECT deptno, COUNT(deptno) count,AVG(sal) avgsal FROM emp GROUP BY deptno) tempWHERE job='MANAGER' AND e.deptno=d.deptno AND temp.deptno=e.deptno;#显示方式
SELECT e.ename,e.sal,d.dname,temp.count,temp.avgsal
FROM emp e 
JOIN dept d ON e.deptno=d.deptno 
JOIN (SELECT deptno, COUNT(deptno) count,AVG(sal) avgsal FROM emp GROUP BY deptno) temp ON temp.deptno=e.deptnoAND job='MANAGER';

在这里插入图片描述

  • 查询出所有薪资高于公司平均薪资的员工编号、姓名、基本工资、职位、雇佣日期、所在部门名称、部门位置、上级领导姓名、工资等级、部门人数、平均工资、平均服务年限。
#隐式方式
SELECT e.empno,e.ename,e.sal,e.job,e.hiredate,d.dname,d.loc,me.ename 领导,s.grade,temp.count,temp.avgsal,temp.avgyear
FROM emp e,dept d,emp me,salgrade s,(SELECT deptno,COUNT(deptno) count,AVG(sal) avgsal,AVG(TIMESTAMPDIFF(MONTH,hiredate,CURDATE())/12) avgyear FROM emp GROUP BY deptno) temp 
WHERE e.deptno=d.deptno AND e.sal>(SELECT AVG(sal) FROM emp)
AND e.mgr=me.empno
AND e.sal BETWEEN s.losal AND s.hisal
AND temp.deptno=e.deptno;#显示方式
SELECT e.empno,e.ename,e.sal,e.job,e.hiredate,d.dname,d.loc,me.ename 领导,s.grade,temp.count,temp.avgsal,temp.avgyear
FROM emp e 
JOIN dept d ON e.deptno=d.deptno AND e.sal>(SELECT AVG(sal) FROM emp)
LEFT JOIN emp me ON e.mgr=me.empno
JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal
JOIN (SELECT deptno,COUNT(deptno) count,AVG(sal) avgsal,AVG(TIMESTAMPDIFF(MONTH,hiredate,CURDATE())/12) avgyear FROM emp GROUP BY deptno) temp ON temp.deptno=e.deptno;

在这里插入图片描述

三、总结

  • ✨✨ 子查询允许结构化的查询,这样就可以把一个查询语句的每个部分隔开。
  • ✨✨子查询提供了另一种方法来执行有些需要复杂的join和union来实现的操作。
  • ✨✨在许多人看来,子查询可读性较高。 而实际上,这也是子查询的由来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/5234.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

8.用python写网路爬虫,Scrapy

前言 Scrapy 是一个流行的网络爬虫框架&#xff0c;它拥有很多简化网站抓取的高级函数。本章中&#xff0c;我们将学习使用 Scrapy 抓取示例网站&#xff0c;目标任务与第2章相同。然后&#xff0c;我们还会介绍 Portia &#xff0c;这是一个基于 Scrapy 的应用&#xff0c;允许…

MATLAB 之 低层绘图操作和光照及材质处理

这里写目录标题 一、低层绘图操作1. 曲线对象2. 曲面对象3. 文本对象4. 其他核心对象4.1 区域块对象4.2 方框对象 二、光照和材质处理1. 光照处理2. 材质处理2.1 图形对象的反射特性2.2 material 函数 一、低层绘图操作 MATLAB 将曲线、曲面、文本等图形均视为对象&#xff0c…

LangChain大型语言模型(LLM)应用开发(三):Chains

LangChain是一个基于大语言模型&#xff08;如ChatGPT&#xff09;用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口&#xff0c;可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互&#x…

LeetCode 75 —— 70. 爬楼梯

LeetCode 75 —— 70. 爬楼梯 一、题目描述&#xff1a; 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法…

《操作系统》- 操作系统的基本概念

目录 一、操作系统的概念1.1 操作系统的分类1.2 计算机系统的构成1.3 操作系统都做了哪些事 二、操作系统的目标和功能2.1 操作系统的目标2.2 操作系统的功能 三、操作系统的特征3.1 并发3.2 共享3.3 虚拟3.4 异步 一、操作系统的概念 1.1 操作系统的分类 UNIX是非常早期的操作…

uniapp监听手机侧滑返回事件。

这篇文章是应一个粉丝的需求更新的&#xff01;你们看我多宠粉&#xff01; 若在App首页&#xff0c;点击手机物理返回键&#xff0c;此时无返回页面可关闭&#xff0c;uni-app默认会提示“再按一次退出应用”&#xff1b;若想自定义退出信息&#xff0c;如修改为&#xff1a;…

UE4/5动画系列(3.通过后期处理动画蓝图的头部朝向Actor,两种方法:1.通过动画层接口的look at方法。2.通过control rig的方法)

目录 蓝图 点积dot Yaw判断 后期处理动画蓝图 动画层接口 ControlRig: 蓝图 首先我们创建一个actor类&#xff0c;这个actor类是我们要看的东西&#xff0c;actor在哪&#xff0c;我们的动物就要看到哪里&#xff08;同样&#xff0c;这个我们也是做一个父类&#xff0…

第2章 k-近邻算法

文章目录 第2章 k-近邻算法2.1k-近邻算法概述2.1.1准备&#xff1a;使用Python导入数据2.1.2实施kNN分类算法 2.2示例&#xff1a;使用k近邻算法改进约会网站的2.2.2分析数据&#xff1a;使用Matplotlib创建散点图2.2.3准备数据&#xff1a;归一化数值2.2.4测试算法 第2章 k-近…

【C++11】左值引用 与 右值引用

定义 左值 / 左值引用 左值&#xff08;Lvalue&#xff09;&#xff1a; 左值是一个表示数据的表达式(如变量名或解引用的指针)&#xff0c;我们可以 对它取地址 可以对它赋值&#xff0c;左值可以出现赋值符号的左边&#xff0c;右值不能出现在赋值符号左边。定义时const修…

网络系统集成实验(五)| 系统集成路由器OSPF动态、综合路由配置

一、前言 该系列文章将会对网络系统集成课程中相关实验进行更新&#xff0c;本篇为第五篇&#xff0c;有关路由器的OSPF、综合路由配置&#xff0c;包括了OSPF的配置实验、单臂路由实验、RIP配置实验、综合实验等。 注意&#xff1a;该实验的后半部分综合实验基于前面的实验&am…

在idea中高并发下的分布式锁以及解决方法

案例:1.互联网秒杀 2.抢优惠卷 3.接口幂 引入pom文件 <packaging>war</packaging><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.8.RELEA…

Python 基本数据类型(三)

文章目录 每日一句正能量数值运算数值类型实例String&#xff08;字符串&#xff09; 每日一句正能量 人的相处&#xff0c;靠的是真心&#xff0c;不是套路。合得来的人&#xff0c;坦诚相待&#xff0c;合不来的人&#xff0c;客气寒暄&#xff1b;谁也别给谁冷脸看&#xff…