SQL子查询详解

在这篇文章中,将探讨SQL子查询这一概念。子查询可以被看作是更大查询中的小部分,类似于拼图中的单个拼块。将从基础开始,回答“什么是子查询?”和“为什么需要它们?”等问题,并探讨不同类型的子查询及其在SQL查询中的应用场景。

目录

  • 概述
  • 引言
  • 什么是SQL子查询?
  • SQL子查询的类型
  • 普通子查询
  • 内联视图
  • 相关子查询
  • SQL子查询的优势
  • 理解数据集
  • 结论

什么是SQL子查询?

SQL子查询就像是一个大问题中的小问题。它通过获取特定信息,然后在主问题中使用这些答案,帮助分解复杂的任务。这是SQL中处理数据更有效的一个技巧。

SQL子查询的类型

有三种类型的SQL子查询:

  • 普通子查询
  • 内联视图
  • 相关子查询

之前学习的例子是普通子查询的完美示例。让通过更多的例子来学习:

假设有一个名为ORDERS的表,其中包含了不同产品在多个类别下特定时间段内的销售记录。表中包含的列有:Order_Id, Category, Product, Sales。

与SELECT语句一起使用的子查询

问题:显示按类别划分的销售百分比。将这样写查询:

SELECT Category, SUM(Sales)/(SELECT SUM(Sales) FROM ORDERS) AS PERC_SALES FROM ORDERS GROUP BY Category

这个查询是如何工作的?首先,执行内部查询:

SELECT SUM(Sales) FROM ORDERS

然后使用这个值执行外部查询。

与WHERE子句一起使用的子查询

问题:显示销售量超过整体平均销售量的记录。将这样写查询:

SELECT * FROM ORDERS WHERE Sales > (SELECT AVG(Sales) FROM ORDERS)

这个查询是如何工作的?首先,执行内部查询:

SELECT AVG(Sales) FROM ORDERS

然后使用这个值执行外部查询。

与HAVING子句一起使用的子查询

问题:显示每个产品的平均销售量超过整体平均销售量的产品。将这样写查询:

SELECT Product, AVG(Sales) FROM ORDERS GROUP BY Product HAVING AVG(Sales) > (SELECT AVG(Sales) FROM ORDERS)

这个查询是如何工作的?首先执行内部查询:

SELECT AVG(Sales) FROM ORDERS

然后使用这个值执行外部查询。

普通子查询的重要特性:

  • 与SELECT语句、WHERE子句、HAVING子句、CASE WHEN语句一起使用。
  • 首先执行子查询(内部查询),然后执行主查询(外部查询),并使用子查询的输出。
  • 内部查询独立工作,也可以查询不同的表。
  • 它最多只能返回一列输出。

让通过一个简单的例子来理解:

要获取表中的所有记录,可以这样做:

SELECT * FROM ORDERS

可以将表(ORDERS)替换为子查询(SELECT * FROM ORDERS),这就是所谓的内联视图。

SELECT * FROM (SELECT * FROM ORDERS) TT

让来看一个更复杂的问题。

问题:显示销售量第二低的记录。将这样写查询:

SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY Sales) AS row_num FROM ORDERS) AS T WHERE row_num=2

这个查询是如何工作的?首先执行内部查询:

SELECT *, ROW_NUMBER() OVER(ORDER BY Sales) AS row_num FROM ORDERS

然后使用这个值执行外部查询。

内联视图的重要特性:

  • 用于FROM子句,即当在FROM子句中写查询时。
  • 它是SELECT语句FROM子句中的子查询。
  • 当已经写了一个查询(称为内部查询),想要使用那个内部查询的输出作为外部查询的表时使用。
  • 必须在FROM子句的末尾写上表别名。
  • 看起来像是嵌套的SELECT语句。

让通过一个例子来学习这个概念:

问题:显示所有产品,其销售量超过其类别中的平均销售量。将这样写查询:

SELECT Order_Id, Product, Category FROM ORDERS ord WHERE Sales >= (SELECT AVG(Sales) FROM ORDERS WHERE Category = ord.Category)

这个查询是如何工作的?子查询针对外部查询的每一行执行一次。

相关子查询的重要特性:

  • 用于逐行处理。
  • 当希望子查询为外部查询(主查询)考虑的每一行返回不同的结果时使用。
  • 可以在相关查询中使用ANY和ALL等操作符。
  • 子查询可以与SELECT、INSERT、UPDATE和DELETE语句一起使用。

SQL子查询的优势

使用SQL子查询有一些明显的好处:

  • 简单性:它们通过将复杂查询分解成更小、更易于处理的部分来简化复杂查询。
  • 清晰性:子查询使代码更易于阅读和理解。
  • 可重用性:可以在查询的不同部分使用子查询,避免重复相同的代码。
  • 效率:它们帮助首先获取特定信息,使主查询运行更快、更顺畅。
  • 灵活性:子查询适应需求的变化,使查询更加灵活。
  • 嵌套操作:可以通过将操作嵌套在子查询中来执行复杂的操作。

因此,使用SQL子查询可以使查询更简单、更清晰、更高效!

将使用这个数据集来展示本文中所有的例子。有一个名为ORDERS的表,其中包含了不同产品在多个类别下特定时间段内的销售记录。表中包含的列有:Order_Id, Category, Product, Sales。

让从一个场景开始学习!假设只想看到销售量超过所有记录平均销售量的条目。

问题:能显示销售量超过整体平均销售量的记录吗?

可以尝试这样做:

SELECT * FROM ORDERS WHERE Sales > AVG(Sales)

但是会得到一个错误!“聚合函数不能出现在WHERE子句中,除非它包含在外部引用的子查询中。”

等等,这里的“子查询”是什么意思?它是一个查询中的查询。可以使用所谓的“子查询”轻松完成这个任务。

SELECT * FROM ORDERS WHERE Sales > (SELECT AVG(Sales) FROM ORDERS)

这里的SELECT AVG(Sales) FROM ORDERS是子查询(也称为内部查询)。

SELECT AVG(Sales) FROM ORDERS输出:

然后这个输出被用作主查询(也称为外部查询)的输入:

SELECT * FROM ORDERS WHERE Sales > (SELECT AVG(Sales) FROM ORDERS)

得到最终的输出:

让正式定义什么是子查询:

什么是子查询?子查询是另一个SQL查询中的查询。注意它必须始终用括号包围。

何时使用子查询?当想要在不同级别执行操作或执行计算时,就像在内部查询中所做的(计算了整体平均销售量)和其他操作在不同级别,就像在外部查询中所做的(将每个记录的个别销售量与整体销售量进行比较)。简而言之,当想要在不同级别执行操作时,使用子查询。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485