SQL Server Subqueries

1. Basic knowledge of subqueries

A subquery is a query nested within a SELECT, INSERT, UPDATE, DELETE statement, or within another subquery.
Subqueries can be used anywhere expressions are allowed.
Example:

USE AdventureWorks2016;
GO
SELECT Ord.SalesOrderID, Ord.OrderDate,
    (SELECT MAX(OrdDet.UnitPrice)
     FROM Sales.SalesOrderDetail AS OrdDet
     WHERE Ord.SalesOrderID = OrdDet.SalesOrderID) AS MaxUnitPrice
FROM Sales.SalesOrderHeader AS Ord;
GO

insert image description here

A subquery is also known as an inner query or inner select, and a statement containing a subquery is also known as an outer query or outer select.

Many Transact-SQL statements that contain subqueries can also be expressed as joins. Other questions can only be asked with subqueries. In Transact-SQL, there is usually no performance difference between a statement that includes a subquery and its semantically equivalent version that does not. However, in some cases where existence must be checked, joins yield better performance. Otherwise, the nested query must be processed for each result of the outer query to ensure that duplicates are eliminated. In this case, the join method will yield better results.

The following examples show subqueries and joins that return the same result set and execution plan:

USE AdventureWorks2016;
GO

/* SELECT statement built using a subquery. */
SELECT [Name]
FROM Production.Product
WHERE ListPrice =
    (SELECT ListPrice
     FROM Production.Product
     WHERE [Name] = 'Chainring Bolts' );
GO

/* SELECT statement built using a join that returns
   the same result set. */
SELECT Prd1.[Name]
FROM Production.Product AS Prd1
     JOIN Production.Product AS Prd2
       ON (Prd1.ListPrice = Prd2.ListPrice)
WHERE Prd2.[Name] = 'Chainring Bolts';
GO

A subquery nested within an outer SELECT statement has the following components:

  • A regular query that includes a regular select list component.
  • A regular clause containing one or more table or view names.
  • Optional: WHERE, GROUP BY, HAVING.

SELECT queries for subqueries are always enclosed in parentheses. It cannot contain an or clause, and can only contain clauses if the TOP clause is also specified.

A subquery can be nested within an outer WHERE , HAVING , SELECT , INSERT , UPDATE , DELETE , or clause of a statement, or within another subquery. Up to 32 levels of nesting are possible, but limits vary with available memory and the complexity of other expressions in the query. A single query may not support up to 32 levels of nesting. A subquery can appear anywhere an expression can be used if the subquery returns a single value.

If a table appears only in the subquery and not in the outer query, the columns from that table cannot be included in the output (the select list of the outer query).

Statements containing subqueries typically take one of the following formats:

  • WHERE expression [NOT] IN (subquery)
  • WHERE expression comparison_operator [ANY | ALL] (subquery)
  • WHERE [NOT] EXISTS (subquery)

In some Transact-SQL statements, subqueries can be evaluated as independent queries. Conceptually, the subquery results are substituted into the outer query (although this is not necessarily how SQL Server actually handles Transact-SQL statements with subqueries).

There are three basic types of subqueries:

  • Operates on the introduced list, or the list modified by the comparison operator INANY or ALL.
  • Introduced with unmodified comparison operators and must return a single value.
  • Whether to introduce an existence test using EXISTS.

2. Subquery rules

  • The select list of a subquery introduced using a comparison operator can contain only one expression or column name.
  • If a clause of the outer query includes column names, that clause must be join-compatible with the columns in the subquery select list.
  • The ntext, text, and image data types cannot be used in the select list of a subquery.
  • Since they must return a single value, subqueries introduced by unmodified comparison operators (not followed by the keyword or) cannot contain an and clause.
  • Keywords cannot be used with contained subqueries.
  • The and clause cannot be specified.
  • ORDER BY can only be specified if TOP is also specified.
  • A view created with a subquery cannot be updated.

3. Limit the column names in the subquery

Example: The BusinessEntityID column in the outer query clause is implicitly qualified by the table name in the outer query clause (Sales.Store). References to CustomerID in the subquery's select list are qualified by the subquery clause (that is, the Sales.Customer table).

USE AdventureWorks2016;
GO
SELECT [Name]
FROM Sales.Store
WHERE BusinessEntityID NOT IN
    (SELECT CustomerID
     FROM Sales.Customer
     WHERE TerritoryID = 5);
GO

In general, column names in a statement are implicitly qualified by tables referenced in clauses at the same level. If the column does not exist in the table referenced in the subquery clause, the table referenced in the outer query clause will implicitly qualify the column.

Here's what a query specifying these implicit assumptions might look like:

USE AdventureWorks2016;
GO
SELECT [Name]
FROM Sales.Store
WHERE Sales.Store.BusinessEntityID NOT IN
    (SELECT Sales.Customer.CustomerID
     FROM Sales.Customer
     WHERE TerritoryID = 5);
GO

It is never wrong to explicitly state a table name, and explicit qualifications can always be used to override implicit assumptions about table names.

4. Multi-layer nesting of subqueries

A subquery can itself contain one or more subqueries. Any number of subqueries can be nested within a statement.

Example: A query finds the names of employees who are also salespeople.

USE AdventureWorks2016;
GO
SELECT LastName, FirstName
FROM Person.Person
WHERE BusinessEntityID IN
    (SELECT BusinessEntityID
     FROM HumanResources.Employee
     WHERE BusinessEntityID IN
        (SELECT BusinessEntityID
         FROM Sales.SalesPerson)
    );
GO

output:

LastName                                           FirstName
-------------------------------------------------- -----------------------
Jiang                                              Stephen
Abbas                                              Syed
Alberts                                            Amy
Ansman-Wolfe                                       Pamela
Campbell                                           David
Carson                                             Jillian
Ito                                                Shu
Mitchell                                           Linda
Reiter                                             Tsvi
Saraiva                                            Jos
Vargas                                             Garrett
Varkey Chudukatil                                  Ranjit
Valdez                                             Rachel
Tsoflias                                           Lynn
Pak                                                Jae
Blythe                                             Michael
Mensa-Annan                                        Tete

(17 row(s) affected)

The innermost query returns the salesperson ID. The next higher level query evaluates with these salesperson IDs and returns the employee's contact ID number. Finally, the outer query uses the contact ID to find the employee's name.

This query can also be expressed as a join:

USE AdventureWorks2016;
GO
SELECT LastName, FirstName
FROM Person.Person c
INNER JOIN HumanResources.Employee e
ON c.BusinessEntityID = e.BusinessEntityID
JOIN Sales.SalesPerson s
ON e.BusinessEntityID = s.BusinessEntityID;
GO

5. Correlated subqueries

Many queries can be evaluated by executing the subquery once and substituting the resulting values ​​into clauses of the outer query. In a query that contains a correlated subquery (also known as a repeated subquery), the subquery depends on the outer query for its values. This means that the subquery will be executed repeatedly, once for each row that the outer query might select.

Example:

USE AdventureWorks2016;
GO
SELECT DISTINCT c.LastName, c.FirstName, e.BusinessEntityID
FROM Person.Person AS c JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = c.BusinessEntityID
WHERE 5000.00 IN
    (SELECT Bonus
    FROM Sales.SalesPerson sp
    WHERE e.BusinessEntityID = sp.BusinessEntityID) ;
GO

Output result:

LastName FirstName BusinessEntityID
-------------------------- ---------- ------------
Ansman-Wolfe Pamela 280
Saraiva José 282

(2 row(s) affected)

The previous subquery in this statement cannot be evaluated independently of the outer query. It requires the value of Employee.BusinessEntityID, but this value changes as SQL Server examines different rows in Employee. This is exactly how this query is evaluated: SQL Server considers each row of the Employee table to be included in the result by substituting the values ​​in each row into the inner query. For example, if the row that SQL Server examines first, the variable Employee.BusinessEntityID takes on the value 285, which SQL Server replaces in the inner query. These two query examples represent a decomposition of the previous example with correlated subqueries.

USE AdventureWorks2016;
GO
SELECT Bonus
FROM Sales.SalesPerson
WHERE BusinessEntityID = 285;
GO

The result is 0.00 (didn't receive the bonus because they weren't a salesperson), so the outer query evaluates to:

USE AdventureWorks2016;
GO
SELECT LastName, FirstName
FROM Person.Person AS c JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = c.BusinessEntityID
WHERE 5000 IN (0.00);
GO

Since this is false, rows from are not included in the results of the previous example query with a correlated subquery. Do the same process for the right row. You will see that this line is included in the result because of the inclusion of the result.

Summary: Correlated subqueries can also include table-valued functions in clauses by referencing columns in the table as arguments to the table-valued function in the outer query. In this case, for each row of the outer query, the table-valued function is evaluated against the subquery.

6. Subquery type

  • with an alias.
  • With IN or NOT IN.
  • In UPDATE, DELETE, and INSERT statements.
  • Use comparison operators.
  • Use ANY, SOME, or ALL.
  • 跟 IS [NOT] DISTINCT FROM。
  • With EXISTS or NOT EXISTS.
  • instead of an expression.

Summarize

If a column referenced in the subquery does not exist in the subquery, but exists in a table referenced by a clause of the outer query, the query will execute without error. SQL Server uses the table name in the outer query to implicitly qualify the columns in the subquery.
insert image description here

Guess you like

Origin blog.csdn.net/Long_xu/article/details/130041492