SQL子查询也称为内部查询、嵌套查询或内部SELECT,是嵌套在另一个查询中的查询。例如,子查询可以嵌套在SELECT、INSERT、DELETE和UPDATE语句中,或嵌套在另一个查询中。
我们主要在WHERE子句中使用子查询。这类似于WHERE expression NOT IN,或IN子query等。对于此SQL Server子查询或嵌套查询演示,我们使用Employee表。

编写子查询或嵌套查询的基本规则。
- 它必须包含在括号内。
- 除非使用TOP子句,否则不能在子查询中使用ORDER BY子句。
- 它必须包含一个常规的SELECT语句和FROM子句。
- 您也可以在SQL子查询或嵌套查询中使用可选的WHERE、GROUP BY子句和HAVING子句。
- 其中不得包含COMPUTE或FOR BROWSE子句。
- 它可以嵌套在外部SELECT、INSERT、DELETE或UPDATE语句的WHERE或HAVING子句中。
- 它允许您将子查询嵌套多达32个级别,称为嵌套查询。这也可能有所不同。
SELECT语句中的SQL子查询
这个简单的例子将在SELECT语句中编写一个嵌套查询。
SELECT sq.FirstName + ' ' + sq.LastName AS [Full Name],
sq.[Occupation], sq.[YearlyIncome],sq.[Sales]
FROM (
SELECT [EmpID],[FirstName]
,[LastName]
,[Education]
,[Occupation]
,[YearlyIncome]
,[Sales]
FROM [EmployeeTb]
WHERE [Sales] > 500
) AS [sq]
内部查询返回Employee表中销售额大于500的所有记录。

主查询从子查询(内部或嵌套查询)中提取或选择所需的列。

SQL子查询SELECT语句示例2
Microsoft Server允许我们将此添加或用作SELECT语句中的列表达式。因此,让我们将其写入SELECT语句。
提示:由于我们将其用作列表达式,因此它必须为由主查询返回的每条记录返回单个值。
SELECT [EmpID]
,[FirstName]
,[LastName]
,[Education]
,[Occupation]
,[YearlyIncome]
,
(
SELECT SUM([YearlyIncome]) FROM [EmployeeTb]
WHERE [Occupation] = 'Professional' OR [Occupation] = 'Management'
) AS [Total Income]
,[Sales]
,[HireDate]
FROM [EmployeeTb]
WHERE [Occupation] = 'Professional' OR [Occupation] = 'Management'

WHERE子句中的子查询
我们也可以将嵌套查询用作WHERE子句中的表达式。通常,我们编写WHERE expression NOT IN或IN。在此示例中,我们展示了如何在WHERE子句中编写它。
SELECT [EmpID]
,[FirstName]
,[LastName]
,[Education]
,[Occupation]
,[YearlyIncome]
,[Sales]
,[HireDate]
FROM [EmployeeTb]
WHERE [Sales] >= (
SELECT AVG([Sales]) FROM [EmployeeTb]
)
首先,它将在WHERE子句中执行内部查询。然后,在内部查询中,我们计算销售额的平均值。
接下来,主查询或外部查询将选择Employee表中销售额超出平均销售额的所有记录。

SQL Server子查询FROM子句
它也可以在FROM子句中使用,这可以帮助我们返回多条记录。例如,以下查询显示了如何在FROM子句中编写它。
SELECT sq.Occupation,
SUM(sq.YearlyIncome) AS Income,
SUM(sq.Sales) AS TotalSale
FROM (
SELECT [EmpID],[FirstName],[LastName]
,[Education],[Occupation]
,[YearlyIncome]
,[Sales]
FROM [EmployeeTb]
WHERE [Sales] > 500
) AS sq
GROUP BY sq.Occupation
首先,将执行子查询或嵌套查询,返回Employee表中销售额大于500的所有记录。
在外部查询中,我们按职业分组并聚合年度收入和销售额。我建议您参考GROUP BY子句以了解结构化查询语言中的聚合和分组。

CASE语句中的嵌套查询
让我们看看如何在SQL Server子查询或嵌套查询中编写CASE语句。
SELECT [EmpID]
,[FirstName] + SPACE(2) + [LastName] AS FullName
,[Education]
,[Occupation]
,[YearlyIncome]
,[Sales]
,CASE WHEN
(
SELECT AVG([Sales]) FROM [EmployeeTb]
) <= emp.[Sales] THEN 'He is Performing Good'
ELSE 'He is Under Performing'
END AS Remarks
,[HireDate]
FROM [EmployeeTb] AS emp
首先,它执行一个子查询,并计算表中销售额的平均值。接下来,我们使用CASE语句检查销售额是否高于平均销售额(1970.9055)。如果表达式返回TRUE,则返回“他表现良好”;否则,返回“他表现不佳”,作为“备注”列的输出。
接下来,主代码选择Employee表中的所有记录以及从CASE语句获得的Remarks列。在这里,我们使用SPACE函数在名字和姓氏之间返回两个空格。

SQL Server中的相关子查询
以上所有查询都是非相关的,因为它们独立运行。让我们看看如何编写相关子查询。这些类型是相互依赖的。我的意思是,内部查询依赖于主查询,反之亦然。
SELECT [EmpID]
,[FirstName] + SPACE(2) + [LastName] AS FullName
,[Education]
,[Occupation]
,[YearlyIncome]
,[Sales]
,CASE WHEN
(
SELECT AVG([Sales]) FROM [EmployeeTb] AS sb
WHERE sb.EmpID = emp.EmpID
) <= emp.[Sales] THEN 'He is Performing Good'
ELSE 'He is Under Performing'
END AS Remarks
,[HireDate]
FROM [EmployeeTb] AS emp
尽管它给出了与上述CASE语句示例相同的结果,但它会为多个Employee表ID运行多次。这是因为子查询在Where子句中需要Employee ID。
WHERE sb.Id = emp.Id
好的,让我独立运行嵌套查询。
Messages
-------
Msg 4104, Level 16, State 1, Line 13
The multi-part identifier "emp.EmpID" could not be bound.
正如您所见,它抛出了一个错误。现在,让我们运行整个代码。

UPDATE语句中的SQL子查询
它也可以在UPDATE语句中使用。它展示了如何在Update语句中编写它来更新Employee表中的记录。
UPDATE [EmployeeTb]
SET [YearlyIncome] = [YearlyIncome] + 25000
WHERE [Sales] > (
SELECT AVG([Sales]) FROM [EmployeeTb]
)
UPDATE语句中的上述示例将通过向销售额大于平均销售额的每个人添加25000(类似于奖金)来更新年度收入。

DELETE语句中的SQL子查询
我们也可以在DELETE语句中使用它。在删除语句中编写子查询以从Employee表中删除行。
DELETE FROM [EmployeeTb]
WHERE [Sales] < (
SELECT AVG([Sales]) FROM [EmployeeTb]
)
上述DELETE语句将删除Employee表中销售额小于平均销售额的记录或行。例如,我们使用嵌套查询来获取平均销售额。

INSERT语句中的子查询
我们也可以在Insert Into Select语句中使用它。例如,在Insert语句中编写子查询以将新记录插入Employee表中。
INSERT INTO [EmployeeTb] ([FirstName]
,[LastName]
,[Education]
,[Occupation]
,[YearlyIncome]
,[Sales]
,[HireDate])
SELECT [FirstName]
,[LastName]
,[Education]
,[Occupation]
,[YearlyIncome]
,[Sales]
,[HireDate]
FROM [EmployeeTbOrginal]
Insert Into Select Statement的输出是
