MySQL必知必会——第十四章使用子查询

2023-10-29

使用子查询

本章介绍什么是子查询以及如何使用它们。

子查询

SELECT语句是SQL的查询,目前我们用的所有SELECT语句都是从单个数据库表中检索数据的单条简单语句。

  • 查询(query) 任何SQL语句都是查询。但此术语一般指SELECT语句。

SQL还允许创建子查询(subquery),即嵌套在其他查询中的查询。


利用子查询进行过滤

检索出订购物品TNT2的所有客户的步骤:

  1. 检索包含物品TNT2的所有订单编号。
  2. 检索具有前一步列出的订单编号的所有客户的ID。
  3. 检索前一步列出的客户ID的客户信息。

以上步骤都可以单独作为一个查询来执行。可以把一条SELECT语句返回的结果用于另一条SELECT语句的WHERE子句。也可以使用子查询把3个查询组合成一条语句。

步骤1:检索prod_id为TNT2的order_num值

mysql> SELECT order_num
    -> FROM orderitems
    -> WHERE prod_id = 'TNT2';
+-----------+
| order_num |
+-----------+
|     20005 |
|     20007 |
+-----------+
2 rows in set (0.02 sec)

步骤2:查询具有订单20005和20007的客户ID

mysql> SELECT cust_id
    -> FROM orders
    -> WHERE order_num IN (20005,20007);
+---------+
| cust_id |
+---------+
|   10001 |
|   10004 |
+---------+
2 rows in set (0.01 sec)

利用子查询合并步骤1和2:

mysql> SELECT cust_id
    -> FROM orders
    -> WHERE order_num IN (SELECT order_num
    ->                     FROM orderitems
    ->                     WHERE prod_id = 'TNT2');
+---------+
| cust_id |
+---------+
|   10001 |
|   10004 |
+---------+
2 rows in set (0.01 sec)

在SELECT语句中,子查询总是从内向外处理。

步骤3:检索这些客户ID的客户信息:

mysql> SELECT cust_name, cust_contact
    -> FROM customers
    -> WHERE cust_id IN (10001,10004);
+----------------+--------------+
| cust_name      | cust_contact |
+----------------+--------------+
| Coyote Inc.    | Y Lee        |
| Yosemite Place | Y Sam        |
+----------------+--------------+
2 rows in set (0.01 sec)

利用子查询合并步骤1、2和3:

mysql> SELECT cust_name, cust_contact
    -> FROM customers
    -> WHERE cust_id IN (SELECT cust_id
    ->                   FROM orders
    ->                   WHERE order_num IN (SELECT order_num
    ->                                       FROM orderitems
    ->                                       WHERE prod_id = 'TNT2'));
+----------------+--------------+
| cust_name      | cust_contact |
+----------------+--------------+
| Coyote Inc.    | Y Lee        |
| Yosemite Place | Y Sam        |
+----------------+--------------+
2 rows in set (0.01 sec)

为了执行此SELECT语句,MySQL实际上必须执行3条SELECT语句。最外层查询确实返回所需数据。

在WHERE子句中使用子查询能够编写出功能很强并且很灵活的SQL语句。对于能嵌套的子查询的数目没有限制,但由于性能的限制,不能嵌套太多的子查询。

虽然子查询一般与IN操作符结合使用,但也可以用于测试等于(=),不等于(<>)等。

  • 格式化SQL 包含子查询的SELECT语句难以阅读和调试。我们把子查询分解为多行并且适当的缩进,能极大的简化子查询的使用。
  • 列必须匹配 使用子查询时,应保证SELECT语句具有与WHERE子句中相同数目的列。
  • 子查询和性能 由于需要多次查询,使用子查询并不总是执行这种类型的数据检索的最有效的方法。

作为计算字段使用子查询

使用子查询的另一方法是创建计算字段。

检索customers表中每个客户的订单总数步骤:

  1. 从customers表中检索客户列表。
  2. 对于检索出的每个客户,统计其在orders表中的订单数目。

可使用SELECT COUNT(*)对表中的行进行计数,可通过WHERE来过滤客户。
对客户10001的订单进行计数:

mysql> SELECT COUNT(*) AS orders
    -> FROM orders
    -> WHERE cust_id = 10001;
+--------+
| orders |
+--------+
|      2 |
+--------+
1 row in set (0.00 sec)

为对每个客户进行COUNT(*)计算,应将COUNT(*)作为子查询:

mysql> SELECT cust_name,
    ->        cust_state,
    ->        (SELECT COUNT(*)
    ->         FROM orders
    ->         WHERE orders.cust_id = customers.cust_id) AS orders
    -> FROM customers
    -> ORDER BY cust_name;
+----------------+------------+--------+
| cust_name      | cust_state | orders |
+----------------+------------+--------+
| Coyote Inc.    | MI         |      2 |
| E Fudd         | IL         |      1 |
| Mouse House    | OH         |      0 |
| Wascals        | IN         |      1 |
| Yosemite Place | AZ         |      1 |
+----------------+------------+--------+
5 rows in set (0.01 sec)

此SELECT语句对customers表中每个客户返回3列:cust_name、cust_state和orders。orders是一个计算字段,它由圆括号中的子查询建立的。该子查询对检索出的每个客户执行一次。

子查询中的WHERE子句使用了完全限定列名(MySQL必知必会——第四章检索数据),这告诉SQL比较orders表中的cust_id和当前的customers表中检索的cust_id。

  • 相关子查询(correlated subquery) 涉及外部查询的子查询。

这种子查询称为相关子查询。任何时候只有列名可能有多义性,就必须使用这种语法(表名和列名由一个句点分隔)。

不使用完全限定列名:

mysql> SELECT cust_name,
    ->        cust_state,
    ->        (SELECT COUNT(*)
    ->         FROM orders
    ->         WHERE cust_id = cust_id) AS orders
    -> FROM customers
    -> ORDER BY cust_name;
+----------------+------------+--------+
| cust_name      | cust_state | orders |
+----------------+------------+--------+
| Coyote Inc.    | MI         |      5 |
| E Fudd         | IL         |      5 |
| Mouse House    | OH         |      5 |
| Wascals        | IN         |      5 |
| Yosemite Place | AZ         |      5 |
+----------------+------------+--------+
5 rows in set (0.01 sec)

很显然,不返回预期结果。在子查询中,存在两个cust_id列,一个在customers中,一个在orders中。如果不完全限定列名,MySQL将假定cust_id是orders表中的cust_id,这形成了自身比较。

虽然子查询有时很有用,但必须注意限制有歧义性的列名。

  • 不止一种解决方案 虽然样例代码运行良好,但它并非解决这种数据检索的最有效的方法。
  • 逐渐增加子查询来建立查询 用子查询测试和调试查询很有技巧性。用子查询建立查询最可靠的方法是逐渐进行,由内到外,逐步测试。这样节省了以后找错误的大量时间,并且提高了查询一开始就正常工作的可能。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL必知必会——第十四章使用子查询 的相关文章

随机推荐

  • linux java进程_Java+Linux,深入内核源码讲解多线程之进程

    之前写了两篇文章 都是针对Linux这个系统的 为什么 我为什么这么喜欢写这个系统的知识 可能就是为了今天的内容多线程系列 现在多线程不是一个面试重点 啊 那如果你能深入系统内核回答这个知识点 面试官会怎么想 你会不会占据面试的主动权 我不
  • c# mysql 二进制图片_ASP.NET(C#) 实现将图片以二进制保存到数据库中 转

    注意 上传大文件时 会出现错误 原因我现在还不知道 数据库名 mydata 表名 table img 字段 id 自动编号 filename 文本 img OLE 对象 default aspx 无标题页 default aspx cs u
  • 【电路】电容(三)——耦合、退耦电容

    一 耦合电容 什么是耦合 两个或两个以上的电路构成一个网络时 若其中某一电路中电流或电压发生变化 能影响到其他电路也发生类似的变化 这种网络叫做耦合电路 耦合的作用就是把某一电路的能量输送 或转换 到其他的电路中去 1 电源 导线 电阻 电
  • 蓝牙core_v5.2协议-4 L2CAP上

    本章节主要讲述蓝牙host层的协议 针对BLE 主要关注L2CAP GATT ATT SMP GAP这几层 根据spec的章节顺序 我们一次讲解 PART A A LOGICAL LINK CONTROL AND ADAPTATION PR
  • python的time各种用法

    1 time Python的time模块提供了许多用于处理时间的功能 以下是一些常用的time模块的函数及其用法 并附有示例 time 返回当前时间的时间戳 自1970年1月1日00 00 00起的秒数 import time curren
  • 基于深度学习的高分辨率遥感图像目标检测技术目前的研究现状

    参考 基于深度学习的高分辨率遥感图像目标检测技术目前的研究现状 云 社区 腾讯云 目录 一 概述 二 通用目标检测方法 1 类不平衡问题 2 复杂背景 3 目标的尺度变化 4 特殊视角 5 小目标 三 特定目标检测 1 城市 2 机场 3
  • C++ STL array 容器(深入了解,一文学会)

    array 容器是 C 11 标准中新增的序列容器 简单地理解 它就是在 C 普通数组的基础上 添加了一些成员函数和全局函数 在使用上 它比普通数组更安全 且效率并没有因此变差 和其它容器不同 array 容器的大小是固定的 无法动态的扩展
  • 若依管理系统部署(SpringCloudAlibaba)

    简介 1 采用前后端分离发模式 微服务版本前端基于RuoYi Vue 2 后端采用Springboot Spring Cloud Alibaba 3 注册中心 配置中心选型Nacos 权限认证使用OAuth2 4 流量控制框架选型Senti
  • 蓝桥杯单片机半小时三等奖代码详解

    半小时三等奖程序是蓝桥杯单片机比赛的基础程序 并不是真正意义上的三等奖 下面我根据自己的理解 对半小时省赛三等奖的程序进行解读 基础操作单元 1 LED灯 2 数码管 3 独立按键 4 矩阵键盘 5 蜂鸣器和继电器 我们的程序也是围绕这几个
  • 实现绝对定位元素水平垂直居中的两种方法

    实现绝对定位元素水平垂直居中的两种方法 平时 用的方法即第一种方法是设置left top值均为50 同时margin left设置为绝对定位元素width的一半取负 margin top设为其height的一半取负 例如 绝对定位元素的wi
  • 前端js 数字金额转换为记账格式 金额格式化

    引用
  • Pycharm安装并搭建Tensorflow开发环境

    Pycharm安装并搭建Tensorflow开发环境 下载并安装pycharm 1 下载 2 pycharm配置python环境 安装tensorflow 1 输入清华仓库镜像 2 创建tensorflow环境 3 启动tensorflow
  • 如何确定K-means算法中的k值?

    1 K means算法 k means算法是机器学习中常用的聚类算法 原理简单实现容易 内存占用量也比较小 但使用这个方法时 需要事先指定将要聚合成的簇数 在先验知识缺乏的情况下 想要确定是非常困难的 目前常用的用来确定的方法主要有两种 肘
  • Sqli-labs之Less-18和Less-19

    Less 18 基于错误的用户代理 头部POST注入 注 这一个模拟的场景是注册登录后的注入 由题意可知 这又是一种新姿势 老方法 查找注入点 发现前面的方法都未成功 且错误回显与正确回显都显示IP 这里写说几个常用请求头 上一篇文章详细讲
  • C# System.Guid.NewGuid()

    C System Guid NewGuid GUID 即Globally Unique Identifier 全球唯一标识符 也称 作 UUID Universally Unique IDentifier GUID是一个通过特定算法产生的二
  • 【C语言】操作符详解(上篇)

    操作符分类 1 算术操作符 2 移位操作符 2 1整数的二进制表示形式 2 2 左移操作符 lt lt 2 3 右移操作符 gt gt 3 位操作符 3 1 3 2 3 3 4 赋值操作符 5 单目操作符 5 1 单目操作符的介绍 5 2
  • C#: 未能加载文件或程序集“xxx“

    导入数据时 发生了异常 错误日志如下 2023 09 11 09 20 49 304 125 FATAL null NPOI POIXMLException gt System Reflection TargetInvocationExce
  • Android上使用AES加密和解密字符串

    废话少说 直接上类的源码 import android util Base64 import java nio charset StandardCharsets import java util Objects import java ut
  • Android屏幕适配很难嘛其实也就那么回事,面试官不讲武德

    前言 大厂面试一直都是程序员圈内摸鱼时间津津乐道的话题 进大厂想必也是无数程序员的梦想 关于 原理 的问题 几乎是现如今Android开发岗必问的问题 尤其在大厂面试中更为突出 有过大厂面试经验的小伙伴应该知道 大厂的面试官一般会基于你的简
  • MySQL必知必会——第十四章使用子查询

    使用子查询 本章介绍什么是子查询以及如何使用它们 子查询 SELECT语句是SQL的查询 目前我们用的所有SELECT语句都是从单个数据库表中检索数据的单条简单语句 查询 query 任何SQL语句都是查询 但此术语一般指SELECT语句