SQL 子查询

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 subquery Example 1

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

Execute Main

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'
subquery Example 4

WHERE子句中的子查询

我们也可以将嵌套查询用作WHERE子句中的表达式。通常,我们编写WHERE expression NOT ININ。在此示例中,我们展示了如何在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子句以了解结构化查询语言中的聚合和分组。

Subquery in Where and From Clause

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函数在名字和姓氏之间返回两个空格。

Subquery in Case Statement

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.

正如您所见,它抛出了一个错误。现在,让我们运行整个代码。

Correlated subquery in SQL Server

UPDATE语句中的SQL子查询

它也可以在UPDATE语句中使用。它展示了如何在Update语句中编写它来更新Employee表中的记录。

UPDATE [EmployeeTb]
SET [YearlyIncome] = [YearlyIncome] + 25000
WHERE [Sales] > (
		SELECT AVG([Sales]) FROM [EmployeeTb]
                )

UPDATE语句中的上述示例将通过向销售额大于平均销售额的每个人添加25000(类似于奖金)来更新年度收入。

SQL Nested Query in Update Statement

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的输出是