iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >SQL 子查询简介
  • 583
分享到

SQL 子查询简介

SQL子查询简介 2019-10-04 12:10:46 583人浏览 绘本
摘要

目录一、子查询和视图二、子查询的名称三、标量子查询四、标量子查询的书写位置五、使用标量子查询时的注意事项请参阅 学习重点 一言以蔽之,子查询就是一次性视图(SELECT 语句)。与视图不同,子查询在 SELECT 语句执行完

SQL 子查询简介

目录
  • 一、子查询和视图
  • 二、子查询的名称
  • 三、标量子查询
  • 四、标量子查询的书写位置
  • 五、使用标量子查询时的注意事项
  • 请参阅

学习重点

  • 一言以蔽之,子查询就是一次性视图(SELECT 语句)。与视图不同,子查询在 SELECT 语句执行完毕之后就会消失。

  • 由于子查询需要命名,因此需要根据处理内容来指定恰当的名称。

  • 标量子查询就是只能返回一行一列的子查询。

一、子查询和视图

前一节我们学习了视图这个非常方便的工具,本节将学习以视图为基础的子查询。子查询的特点概括起来就是一张一次性视图。

KEYWORD

  • 子查询

我们先来复习一下视图的概念,视图并不是用来保存数据的,而是通过保存读取数据的 SELECT 语句的方法来为用户提供便利。反之,子查询就是将用来定义视图的 SELECT 语句直接用于 FROM 子句当中。接下来,就让我们拿前一节使用的视图 ProductSum(商品合计)来与子查询进行一番比较吧。

首先,我们再来看一下视图 ProductSum 的定义和视图所对应的 SELECT 语句(代码清单 8)。

代码清单 8 视图 ProductSum 和确认用的 SELECT 语句

-- 根据商品种类统计商品数量的视图
CREATE VIEW ProductSum (product_type, cnt_product)
AS
SELECT product_type, COUNT(*)
  FROM Product
 GROUP BY product_type;

-- 确认创建好的视图
SELECT product_type, cnt_product
  FROM ProductSum;

能够实现同样功能的子查询如代码清单 9 所示。

代码清单 9 子查询

子查询

特定的 SQL

oracleFROM 子句中,不能使用 AS(会发生错误),因此,在 Oracle 中执行代码清单 9 时,需要将 ① 中的“) AS ProductSum;”变为“) ProductSum;

两种方法得到的结果完全相同。

执行结果

 product_type | cnt_product
--------------+------------
 衣服         |           2
 办公用品     |           2
 厨房用具     |           4

如上所示,子查询就是将用来定义视图的 SELECT 语句直接用于 FROM 子句当中。虽然“AS ProductSum”就是子查询的名称,但由于该名称是一次性的,因此不会像视图那样保存在存储介质(硬盘)之中,而是在 SELECT 语句执行之后就消失了。

实际上,该 SELECT 语句包含嵌套的结构,首先会执行 FROM 子句中的 SELECT 语句,然后才会执行外层的 SELECT 语句(图 4)。

SELECT 语句的执行顺序

图 4 SELECT 语句的执行顺序

① 首先执行 FROM 子句中的 SELECT 语句(子查询)

SELECT product_type, COUNT(*) AS cnt_product
  FROM Product
 GROUP BY product_type;

② 根据 ① 的结果执行外层的 SELECT 语句

SELECT product_type, cnt_product
  FROM ProductSum;

法则 6

子查询作为内层查询会首先执行。

  • 增加子查询的层数

    由于子查询的层数原则上没有限制,因此可以像“子查询的 FROM 子句中还可以继续使用子查询,该子查询的 FROM 子句中还可以再使用子查询……”这样无限嵌套下去(代码清单 10)。

    代码清单 10 尝试增加子查询的嵌套层数

    SQL Server DB2 PostgreSQL MySQL

    SELECT product_type, cnt_product
    FROM (SELECT *
            FROM (SELECT product_type, COUNT(*) AS cnt_product
                    FROM Product
                    GROUP BY product_type) AS ProductSum -----①
            WHERE cnt_product = 4) AS ProductSum2; -----------②
    

    特定的 SQL

    在 Oracle 的 FROM 子句中不能使用 AS(会发生错误),因此,在 Oracle 中执行代码清单 10 时,需要将 ① 中的“) AS ProductSum”变为“) ProductSum”,将 ② 中的“) AS ProductSum2;”变为“) ProductSum2;”。

    执行结果

    product_type | cnt_product
    --------------+------------
    厨房用具     |           4
    

    最内层的子查询(ProductSum)与之前一样,根据商品种类(product_type)对数据进行汇总,其外层的子查询将商品数量(cnt_product)限定为 4,结果就得到了 1 行厨房用具的数据。

    但是,随着子查询嵌套层数的增加,sql 语句会变得越来越难读懂,性能也会越来越差。因此,请大家尽量避免使用多层嵌套的子查询。

二、子查询的名称

之前的例子中我们给子查询设定了 ProductSum 等名称。原则上子查询必须设定名称,因此请大家尽量从处理内容的角度出发为子查询设定恰当的名称。在上述例子中,子查询用来对 Product 表的数据进行汇总,因此我们使用了后缀 Sum 作为其名称。

为子查询设定名称时需要使用 AS 关键字,该关键字有时也可以省略 [1]

三、标量子查询

接下来我们学习子查询中的标量子查询Scalar subquery)。

KEYWORD

  • 标量子查询
  • 什么是标量

    标量就是单一的意思,在数据库之外的领域也经常使用。

    KEYWORD

    • 标量

    上一节我们学习的子查询基本上都会返回多行结果(虽然偶尔也会只返回 1 行数据)。由于结构和表相同,因此也会有查询不到结果的情况。

    而标量子查询则有一个特殊的限制,那就是必须而且只能返回 1 行 1 列的结果,也就是返回表中某一行的某一列的值,例如“10”或者“东京都”这样的值。

    KEYWORD

    • 返回值

      返回值就是函数或者 SQL 语句等处理执行之后作为结果返回的值。

    法则 7

    标量子查询就是返回单一值的子查询。

    细心的读者可能会发现,由于返回的是单一的值,因此标量子查询的返回值可以用在 = 或者 <> 这样需要单一值的比较运算符之中。这也正是标量子查询的优势所在。下面就让我们赶快来试试看吧。

  • WHERE 子句中使用标量子查询

    在 数据的删除 中,我们练习了通过各种各样的条件从 Product(商品)表中读取数据。大家有没有想过通过下面这样的条件查询数据呢?

    “查询出销售单价高于平均销售单价的商品。”

    或者说想知道价格处于上游的商品时,也可以通过上述条件进行查询。

    然而这并不是用普通方法就能解决的。如果我们像下面这样使用 AVG 函数的话,就会发生错误。

    在 WHERE 子句中不能使用聚合函数

    虽然这样的 SELECT 语句看上去能够满足我们的要求,但是由于在 WHERE 子句中不能使用聚合函数,因此这样的 SELECT 语句是错误的。

    那么究竟什么样的 SELECT 语句才能满足上述条件呢?

    这时标量子查询就可以发挥它的功效了。首先,如果想要求出 Product 表中商品的平均销售单价(sale_price),可以使用代码清单 11 中的 SELECT 语句。

    代码清单 11 计算平均销售单价的标量子查询

    SELECT AVG(sale_price)
    FROM Product;
    

    执行结果

            avg
    ----------------------
    2097.5000000000000000
    

    AVG 函数的使用方法和 COUNT 函数相同,其计算式如下所示。

    (1000+500+4000+3000+6800+500+880+100) / 8=2097.5

    这样计算出的平均单价大约就是 2100 日元。不难发现,代码清单 11 中的 SELECT 语句的查询结果是单一的值(2097.5)。因此,我们可以直接将这个结果用到之前失败的查询之中。正确的 SQL 如代码清单 12 所示。

    代码清单 12 选取出销售单价(sale_price)高于全部商品的平均单价的商品

    选取出销售单价(sale_price)高于全部商品的平均单价的商品

    执行结果

    product_id | product_name | sale_price
    ------------+--------------+-----------
    0003       | 运动T恤      |       4000
    0004       | 菜刀         |       3000
    0005       | 高压锅       |       6800
    

    前一节我们已经介绍过,使用子查询的 SQL 会从子查询开始执行。因此,这种情况下也会先执行下述计算平均单价的子查询(图 5)。

    SELECT 语句的执行顺序(标量子查询)

    图 5 SELECT 语句的执行顺序(标量子查询)

    -- ① 内层的子查询
    SELECT AVG(sale_price)
    FROM Product;
    

    子查询的结果是 2097.5,因此会用该值替换子查询的部分,生成如下 SELECT 语句。

    -- ② 外层的查询
    SELECT product_id, product_name, sale_price
    FROM Product
    WHERE sale_price > 2097.5
    

    大家都能看出该 SQL 没有任何问题可以正常执行,结果如上所述。

四、标量子查询的书写位置

标量子查询的书写位置并不仅仅局限于 WHERE 子句中,通常任何可以使用单一值的位置都可以使用。也就是说,能够使用常数或者列名的地 方,无论是 SELECT 子句、GROUP BY 子句、HAVING 子句,还是 ORDER BY 子句,几乎所有的地方都可以使用

例如,在 SELECT 子句当中使用之前计算平均值的标量子查询的 SQL 语句,如代码清单 13 所示。

代码清单 13 在 SELECT 子句中使用标量子查询

在 SELECT 子句中使用标量子查询

执行结果

 product_id | product_name  | sale_price |       avg_price
------------+---------------+------------+----------------------
 0001       | T恤衫         |       1000 | 2097.5000000000000000
 0002       | 打孔器        |        500 | 2097.5000000000000000
 0003       | 运动T恤       |       4000 | 2097.5000000000000000
 0004       | 菜刀          |       3000 | 2097.5000000000000000
 0005       | 高压锅        |       6800 | 2097.5000000000000000
 0006       | 叉子          |        500 | 2097.5000000000000000
 0007       | 擦菜板        |        880 | 2097.5000000000000000
 0008       | 圆珠笔        |        100 | 2097.5000000000000000

从上述结果可以看出,在商品一览表中加入了全部商品的平均单价。有时我们会需要这样的单据。

此外,我们还可以像代码清单 14 中的 SELECT 语句那样,在 HAVING 子句中使用标量子查询。

代码清单 14 在 HAVING 子句中使用标量子查询

在 HAVING 子句中使用标量子查询

执行结果

 product_type |         avg
--------------+----------------------
 衣服         | 2500.0000000000000000
 厨房用具     | 2795.0000000000000000

该查询的含义是想要选取出按照商品种类计算出的销售单价高于全部商品的平均销售单价的商品种类。如果在 SELECT 语句中不使用 HAVING 子句的话,那么平均销售单价为 300 日元的办公用品也会被选取出来。但是,由于全部商品的平均销售单价是 2097.5 日元,因此低于该平均值的办公用品会被 HAVING 子句中的条件排除在外。

五、使用标量子查询时的注意事项

最后我们来介绍一下使用标量子查询时的注意事项,那就是该子查询绝对不能返回多行结果。也就是说,如果子查询返回了多行结果,那么它就不再是标量子查询,而仅仅是一个普通的子查询了,因此不能被用在 = 或者 <> 等需要单一输入值的运算符当中,也不能用在 SELECT 等子句当中。

例如,如下的 SELECT 子查询会发生错误。

如下的 SELECT 子查询会发生错误

发生错误的原因很简单,就是因为会返回如下多行结果。

         avg
----------------------
2500.0000000000000000
300.0000000000000000
2795.0000000000000000

在 1 行 SELECT 子句之中当然不可能使用 3 行数据。因此,上述 SELECT 语句会返回“因为子查询返回了多行数据所以不能执行”这样的错误信息 [2]

请参阅

  • 视图
  • 子查询
  • 关联子查询

(完)


  1. 其中也有像 Oracle 这样,在名称之前使用 AS 关键字就会发生错误的数据库,大家可以将其视为例外的情况。 ↩︎

  2. 例如,使用 postgresql 时会返回如下错误:“ERROR :副查询中使用了返回多行结果的表达式” ↩︎

您可能感兴趣的文档:

--结束END--

本文标题: SQL 子查询简介

本文链接: https://www.lsjlt.com/news/8932.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SQL 子查询简介
    目录一、子查询和视图二、子查询的名称三、标量子查询四、标量子查询的书写位置五、使用标量子查询时的注意事项请参阅 学习重点 一言以蔽之,子查询就是一次性视图(SELECT 语句)。与视图不同,子查询在 SELECT 语句执行完...
    99+
    2019-10-04
    SQL 子查询简介
  • SQL 关联子查询
    目录一、普通的子查询和关联子查询的区别二、关联子查询也是用来对集合进行切分的三、结合条件一定要写在子查询中请参阅 学习重点 关联子查询会在细分的组内进行比较时使用。 关联子查询和 GROUP BY 子句一样,也可以对表中的数据进...
    99+
    2016-06-28
    SQL 关联子查询
  • SQL子查询的感悟
    今天在听陈华军老师的课时;感触颇多。其中讲到“不同执行计划的选择(子查询)”这一栏。我们在平时工作也经常要用到子查询。有哪些思路来优化这种子查询呢? 例如我们今天实验的表结构 表T1 有10000条记录;并在id字段创建btre...
    99+
    2019-02-22
    SQL子查询的感悟
  • SQL子查询怎么使用
    这篇“SQL子查询怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“SQL子查询怎么使用”文章吧。SQL子查询或称为内部...
    99+
    2023-06-27
  • SQL 入门教程:子查询
    目录一、利用子查询进行过滤请参阅 目录汇总:SQL 入门教程:面向萌新小白的零基础入门教程 SELECT 语句 是 SQL 的查询。我们迄今为止所看到的所有 SELECT 语句都是简单查询,即从单个数据库表中检索数据的单条语句。 ...
    99+
    2017-11-30
    SQL 入门教程:子查询
  • SQL如何实现子查询
    这篇文章主要为大家展示了“SQL如何实现子查询”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“SQL如何实现子查询”这篇文章吧。 1...
    99+
    2022-10-19
  • SQL Server的子查询详解
    目录一、子查询基础知识二、子查询规则三、限定子查询中的列名四、子查询的多层嵌套五、相关子查询六、子查询类型总结一、子查询基础知识 子查询是嵌套在SELECT、INSERT、UPDATE、DELETE语句中或另一个...
    99+
    2023-04-12
    SQL Server子查询语句 SQL Server子查询
  • MySQL查询优化的简介
    这篇文章给大家分享的是有关MySQL查询优化的简介的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。前言MySQL是关系性数据库中的一种,查询功能强,数据一致性高,数据安全性高,支持...
    99+
    2022-10-18
  • MySQL子查询Subquery语法介绍
    下面讲讲关于MySQL子查询Subquery,文字的奥妙在于贴近主题相关。所以,闲话就不谈了,我们直接看下文吧,相信看完MySQL子查询Subquery这篇文章你一定会有所受益。子查询, 是指在SQL语句中...
    99+
    2022-10-18
  • SQL Server2019数据库之简单子查询的具有方法
    子查询可以完成 SQL 查询中比较复杂的情况,本章主要介绍一些子查询的简单用法。 一、简单子查询 1、简单子查询 子查询是 SELECT 语句内的另外一条 SELECT 语句...
    99+
    2022-11-12
  • sql递归查询父子节点
    一、表结构 二、递归查询当前节点的所有父节点 select * from test start with id = 3 connect by prior pid = id 三、递归查询当前节点的所有子节点 sele...
    99+
    2014-07-18
    sql递归查询父子节点
  • SQL 基础之子查询(十一)
    子查询:类型、语法、和注意事项使用子查询能解决哪些问题?子查询语法:select select_list from table where expr operator (selec...
    99+
    2022-10-18
  • Mysql---子查询的三种查询方式( 表子查询,条件子查询,列中子查询)
    mysql子查询 子查询分为: 列中子查询 单列单行表子查询 必须有别名条件子查询 单行单列 多行单列 下列示例表结构: grade表: result表: student表: subject表:...
    99+
    2023-09-04
    mysql sql 数据库
  • MySQL子查询详解(单行子查询、多行子查询与相关子查询)
    目录0.概念1.需求分析与问题解决1.1提出具体问题:1.2 子查询的基本使用: 子查询的基本语法结构:1.3 子查询的分类2.单行子查询2.1实例:2.2空值问题2.3非法使用子查...
    99+
    2022-11-13
  • SQL关联查询 直接join 和子查询的区别
    运营组的同事最近提出一个需求,希望可以统计出用系统用户及订单情况,于是乎我们很想当然的写出了一个统计SQL,用户表user和行程表直接join,并且针对行程做了group,但SQL执行速度出奇的慢。 exp...
    99+
    2022-10-18
  • 如何理解SQL子查询优化
    这篇文章主要介绍“如何理解SQL子查询优化”,在日常操作中,相信很多人在如何理解SQL子查询优化问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何理解SQL子查询优化”的疑惑...
    99+
    2022-10-18
  • SQL Server中怎么实现子查询
    这篇文章将为大家详细讲解有关SQL Server中怎么实现子查询,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1、子查询概念介绍子查询可以嵌套在SELEC&...
    99+
    2022-10-18
  • SQL Server子查询的深入理解
    当由where子句指定的搜索条件指向另一张表时,就需要使用子查询或嵌套查询。 1 子查询 子查询是一个嵌套在select、insert、update或delete语句或其他...
    99+
    2022-11-12
  • Oracle在PL/SQL中使用子查询
    目录一、概述1、单行子查询(子查询只返回一行)2、多行单列子查询(子查询返回多行)3、多列子查询二、在DDL语句中使用子查询1、create table2、create View3、...
    99+
    2022-11-13
  • 很好用的mysql父子集查询SQL(根据父级查询所有子集)
    在表中一定要有id和pid,这样才能使用该sql。 需求1: 根据pid查询出其下的所有子集(比如,子集的子集的子集…)全部查询出来。 首先,在表中按照父节点(parent_id)和id字段(id)的...
    99+
    2023-09-01
    sql mysql 数据库
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作