在这篇文章中,将探讨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 * 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
然后使用这个值执行外部查询。
内联视图的重要特性:
让通过一个例子来学习这个概念:
问题:显示所有产品,其销售量超过其类别中的平均销售量。将这样写查询:
SELECT Order_Id, Product, Category FROM ORDERS ord WHERE Sales >= (SELECT AVG(Sales) FROM ORDERS WHERE Category = ord.Category)
这个查询是如何工作的?子查询针对外部查询的每一行执行一次。
相关子查询的重要特性:
使用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查询中的查询。注意它必须始终用括号包围。
何时使用子查询?当想要在不同级别执行操作或执行计算时,就像在内部查询中所做的(计算了整体平均销售量)和其他操作在不同级别,就像在外部查询中所做的(将每个记录的个别销售量与整体销售量进行比较)。简而言之,当想要在不同级别执行操作时,使用子查询。