【08】MySQL复杂查询:子查询语句详解与示例

文章目录

  • 一、子查询的基本概念
    • 子查询的基本结构
    • 子查询的类型
  • 二、标量子查询
    • 示例 1:标量子查询
    • 示例 2:标量子查询与IN组合
  • 三、多行子查询
    • 示例 1:多行子查询与IN
    • 示例 2:多行子查询与ANY
  • 四、多列子查询
    • 示例 1:多列子查询
  • 五、相关子查询
    • 示例 1:相关子查询
    • 示例 2:使用EXISTS与相关子查询
  • 六、子查询的优化
  • 七、总结

在这里插入图片描述


MySQL子查询(Subquery)是指在一个查询语句中嵌套另一个查询语句。子查询常用于实现复杂的查询逻辑,帮助我们在主查询中引用计算出的结果。子查询通常分为标量子查询、多行子查询、多列子查询以及相关子查询,它们在查询中发挥着不同的作用。本文将详细解析MySQL中子查询的基本语法、分类以及常见的使用场景,并结合具体示例进行说明。

一、子查询的基本概念

子查询通常被用作SELECT、FROM、WHERE、HAVING等子句的一部分,目的是通过另一个查询语句的结果来帮助主查询完成复杂的数据提取。子查询可以在查询中作为输入,提供一个临时的结果集。MySQL允许子查询返回单个值、多个值或者甚至一个完整的表。

子查询的基本结构

SELECT column1, column2, ...
FROM table_name
WHERE column_name OPERATOR (SELECT column_name FROM table_name WHERE condition);

子查询的类型

  1. 标量子查询:返回单个值(例如单个列、单行)。
  2. 多行子查询:返回多个行,但是每行只有一个列。
  3. 多列子查询:返回多个列的数据。
  4. 相关子查询:子查询的结果依赖于外层查询中的某些列。

二、标量子查询

标量子查询返回单个值,这个值可以作为条件与外层查询结合。常见的应用场景是用于WHERE子句中与一个常量进行比较。

示例 1:标量子查询

假设我们有一个员工表 employees,其中包含字段 salary 和 department_id,我们要查询比部门ID为3的员工薪水更高的所有员工。

SELECT first_name, last_name, salary
FROM employees
WHERE salary > (
    SELECT salary
    FROM employees
    WHERE department_id = 3
    LIMIT 1
);

解释:

  1. 子查询 (SELECT salary FROM employees WHERE department_id = 3 LIMIT 1) 返回部门ID为3的员工的薪水。
  2. 主查询从 employees 表中返回所有薪水高于该薪水的员工信息。

示例 2:标量子查询与IN组合

假设我们有两个表:employees 和 departments,我们要查询属于 “Sales” 或 “Marketing” 部门的员工信息。

SELECT first_name, last_name
FROM employees
WHERE department_id IN (
    SELECT department_id
    FROM departments
    WHERE department_name IN ('Sales', 'Marketing')
);

解释:

  1. 子查询 (SELECT department_id FROM departments WHERE department_name IN (‘Sales’, ‘Marketing’)) 返回属于 “Sales” 或 “Marketing” 部门的 department_id。
  2. 主查询通过 IN 子句来过滤出这些部门下的员工。

三、多行子查询

多行子查询返回多个值,通常与IN、ANY、ALL等操作符一起使用。它可以返回一个列的多个值供外层查询使用。

示例 1:多行子查询与IN

假设我们有一个 employees 表,其中有 salary 和 department_id 字段。我们要查询薪资高于所有部门平均薪资的员工。

SELECT first_name, last_name, salary
FROM employees
WHERE salary > ALL (
    SELECT AVG(salary)
    FROM employees
    GROUP BY department_id
);

解释:

  1. 子查询 (SELECT AVG(salary) FROM employees GROUP BY department_id) 计算每个部门的平均薪资。
  2. 主查询返回薪资高于所有部门平均薪资的员工。

示例 2:多行子查询与ANY

假设我们要查询薪资高于某些部门最高薪资的员工,我们可以用 ANY 操作符。

SELECT first_name, last_name, salary
FROM employees
WHERE salary > ANY (
    SELECT MAX(salary)
    FROM employees
    GROUP BY department_id
);

解释:

  1. 子查询 (SELECT MAX(salary) FROM employees GROUP BY department_id) 返回每个部门的最高薪水。
  2. 主查询返回薪水大于某些部门最高薪水的员工。

四、多列子查询

多列子查询返回多个列的结果。与单列子查询不同,主查询的条件需要与子查询的多个列进行匹配。

示例 1:多列子查询

假设我们有两个表:employees 和 departments,我们要查询在"Sales"部门的员工信息,并且薪资高于部门最高薪资。

SELECT first_name, last_name, salary
FROM employees
WHERE (department_id, salary) = (
    SELECT department_id, MAX(salary)
    FROM employees
    WHERE department_id = (
        SELECT department_id FROM departments WHERE department_name = 'Sales'
    )
    GROUP BY department_id
);

解释:

  1. 内层子查询 (SELECT department_id FROM departments WHERE department_name = ‘Sales’) 获取 “Sales” 部门的 department_id。
  2. 中层子查询 (SELECT department_id, MAX(salary)…) 获取该部门的最高薪资和部门ID。
  3. 外层查询筛选出该部门薪资等于最高薪资的员工。

五、相关子查询

相关子查询与普通子查询不同,它依赖于外层查询中的字段。每次执行子查询时,外层查询中的一行都会传递给子查询。相关子查询通常用于需要逐行比较的情况。

示例 1:相关子查询

假设我们有一个 employees 表和一个 departments 表,我们要查询薪水高于同部门所有其他员工薪水的员工。

SELECT first_name, last_name, salary
FROM employees e1
WHERE salary > (
    SELECT MAX(salary)
    FROM employees e2
    WHERE e1.department_id = e2.department_id
    AND e1.employee_id != e2.employee_id
);

解释:

  1. 子查询 (SELECT MAX(salary) FROM employees e2 WHERE e1.department_id = e2.department_id AND e1.employee_id != e2.employee_id) 返回与外层查询同部门的所有其他员工的最高薪资。
  2. 外层查询返回薪资高于该部门其他员工薪资的员工。

示例 2:使用EXISTS与相关子查询

假设我们要查询有员工的部门信息,使用 EXISTS 来判断部门是否有员工。

SELECT department_name
FROM departments d
WHERE EXISTS (
    SELECT 1
    FROM employees e
    WHERE e.department_id = d.department_id
);

解释:

  1. 子查询 (SELECT 1 FROM employees e WHERE e.department_id = d.department_id) 检查是否存在某个部门有员工。
  2. EXISTS 关键字用于判断子查询是否返回结果,只有在子查询有结果时,外层查询才会返回该部门的名称。

六、子查询的优化

子查询在某些情况下可能会导致性能问题,尤其是当子查询的结果集非常大时。以下是一些优化建议:

  • 避免多次计算相同的子查询:如果子查询结果在多个地方使用,可以将其结果存储到临时表中,避免重复执行。
  • 使用连接代替子查询:在很多情况下,可以使用 JOIN 来替代子查询。JOIN 通常比子查询效率更高,因为它通过索引来加速查询。
  • 避免在WHERE子句中使用子查询:在可能的情况下,考虑使用JOIN 或 EXISTS,这些方式通常比在 WHERE 子句中嵌套子查询更高效。

七、总结

MySQL的子查询功能强大,能够在许多复杂查询中帮助我们提取数据。通过标量子查询、多行子查询、多列子查询和相关子查询,开发者可以灵活地在查询中使用嵌套查询,处理各种复杂的数据需求。了解并掌握子查询的语法和优化技巧,将帮助你在数据库设计和查询过程中更加高效地操作数据。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ApiPost调试问题

在使用ApiPost调试接口时,发现传参老是传不过去,最后发现json格式中开头需要小写(哪怕后端名称是大写)

微信 创建小程序码-有数量限制

获取小程序码:小程序码为圆图,有数量限制。 目录 文档 接口地址 功能描述 注意事项 请求参数 对接 获取小程序码 调用获取 小程序码示例 总结 文档 接口地址 https://api.weixin.qq.com/wxa/getwxacode?access_tokenaccess_token 功能描述 …

解决python 使用pip 安装模块时遇到的错误SSL: CERTIFICATE_VERIFY_FAILED

最近有一个使用python 2.7.* 使用requests模块的需求,在安装的过程中遇到了一个问题,在这里分享给大家! 安装requests命令如下 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests 遗憾的是,报错了 Collecting requests …

详解Java数据库编程之JDBC

目录 首先创建一个Java项目 在Maven中央仓库下载mysql connector的jar包 针对MySQL版本5 针对MySQL版本8 下载之后,在IDEA中创建的项目中建立一个lib目录,然后把刚刚下载好的jar包拷贝进去,然后右键刚刚添加的jar包,点击‘添…

Python毕业设计选题:基于大数据的淘宝电子产品数据分析的设计与实现-django+spark+spider

开发语言:Python框架:djangoPython版本:python3.7.7数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 管理员登录 管理员功能界面 电子产品管理 系统管理 数据可视化分析看板展示 摘要 本…

Transformers在计算机视觉领域中的应用【第3篇:Swin Transformer——多层次的Vision Transformer】

目录 1 介绍2 摘要3 模型架构4 窗口自注意力5 移动窗口自注意力5.1 巧妙的掩码方式5.2 相对位置编码 6 总结 论文:Swin Transformer: Hierarchical Vision Transformer using Shifted Windows 代码:https://github.com/microsoft/Swin-Transformer Huggi…

江南大学《2024年807自动控制原理真题》 (完整版)

本文内容,全部选自自动化考研联盟的:《江南大学807自控考研资料》的真题篇。后续会持续更新更多学校,更多年份的真题,记得关注哦~ 目录 2024年真题 Part1:2024年完整版真题 2024年真题

opencvocr识别手机摄像头拍摄的指定区域文字,文字符合规则就语音报警

安装python,pycharm,自行安装。 Python下安装OpenCv 2.1 打开cmd,先安装opencv-python pip install opencv-python --user -i https://pypi.tuna.tsinghua.edu.cn/simple2.2 再安装opencv-contrib-python pip install opencv-contrib-python --user …

Cursor+Devbox AI开发快速入门

1. 前言 今天无意间了解到 Cursor 和 Devbox 两大开发神器,初步尝试以后发现确实能够大幅度提升开发效率,特此想要整理成博客以供大家快速入门. 简单理解 Cursor 就是一款结合AI大模型的代码编辑器,你可以将自己的思路告诉AI,剩下的目录结构的搭建以及项目代码的实现均由AI帮…

【开源】A060-基于Spring Boot的游戏交易系统的设计与实现

🙊作者简介:在校研究生,拥有计算机专业的研究生开发团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看项目链接获取⬇️,记得注明来意哦~🌹 赠送计算机毕业设计600个选题ex…

【笔记】离散数学 1-3 章

1. 数理逻辑 1.1 命题逻辑的基本概念 1.1.1 命题的概念 命题(Proposition):是一个陈述句,它要么是真的(true),要么是假的(false),但不能同时为真和假。例如…

JAVA 架构师面试 100套含答案:JVM+spring+ 分布式 + 并发编程》...

今年的行情,让招聘面试变得雪上加霜。已经有不少大厂,如腾讯、字节跳动的招聘名额明显减少,面试门槛却一再拔高,如果不用心准备,很可能就被面试官怼得哑口无言,甚至失去了难得的机会。 现如今,…

架构10-可观测性

零、文章目录 架构10-可观测性 1、可观测性 (1)可观测性的背景 **历史沿革:**可观测性最初由匈牙利数学家鲁道夫卡尔曼提出,用于线性动态控制系统。后来,该概念被引入到计算机科学中。**现代意义:**在分…

Halcon 瑕疵检测原理及应用

摘要: 本文详细阐述了 Halcon 在瑕疵检测领域的原理、相关技术以及广泛的应用场景。首先介绍了 Halcon 软件的基本概况及其在机器视觉领域的重要地位,接着深入剖析了瑕疵检测所涉及的图像采集、预处理、特征提取与分析以及分类与判定等核心原理&#xff…

开发手札:Win+Mac下工程多开联调

最近完成一个Windows/Android/IOS三端多人网络协同项目V1.0版本,进入测试流程了。为了方便自测,需要用unity将一个工程打开多次,分别是Win/IOS/Android版本,进行多角色联调。 在Win开发机上,以Windows版本为主版…

云原生数据库 PolarDB

PolarDB 是阿里云推出的一款云原生数据库,旨在为企业提供高性能、高可靠性的数据库解决方案。它基于云计算环境设计,特别适用于云上的大规模数据处理和存储需求。PolarDB 是一种兼具关系型数据库(RDS)和分布式数据库特性的新型数据…

状态模式的理解和实践

在软件开发中,我们经常遇到需要根据对象的不同状态执行不同行为的情况。如果直接将这些状态判断和行为逻辑写在同一个类中,会导致该类变得臃肿且难以维护。为了解决这个问题,状态模式(State Pattern)应运而生。状态模式…

【Linux篇】权限管理 - 用户与组权限详解

一. 什么是权限? 首先权限是限制人的。人 真实的人 身份角色 权限 角色 事物属性 二. 认识人–用户 Linux下的用户分为超级用户和普通用户 root :超级管理员,几乎不受权限的约束普通用户 :受权限的约束超级用户的命令提示符是#,普通用…

Java刷题常见的集合类,各种函数的使用以及常见的类型转化等等

前言 相信大家在刷算法题的过程中,好不容易想出来大概的思路,也知道去用哪个集合类,但各个集合类的一些命令都长得太像,很容易将他们弄错,并且在各集合之间的转化也是特别烦人,还有很多实用的函数都知道可…

cgo内存泄漏排查

示例程序&#xff1a; package main/* #include <stdlib.h> #include <string.h> #include <stdio.h> char* cMalloc() {char *mem (char*)malloc(1024 * 1024 * 16);return mem; } void cMemset(char* mem) {memset(mem, -, 1024 * 1024 * 16); } int arr…