Noções básicas sobre subconsultas

Uma subconsulta é uma consulta aninhada em uma instrução SELECT, INSERT, UPDATE ou DELETE, ou em subconsulta. Uma subconsulta pode ser usada em qualquer lugar em que é permitida uma expressão. Neste exemplo, uma subconsulta é usada como uma expressão de coluna denominada MaxUnitPrice em uma instrução SELECT.

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

Uma subconsulta também é chamada de uma consulta interna ou seleção interna, enquanto a instrução que contém uma subconsulta também é chamada de uma consulta externa ou seleção externa.

Muitas instruções Transact-SQL que incluem subconsultas podem ser alternativamente formuladas como junções. Outras perguntas só podem ser feitas com subconsultas. Em Transact-SQL, normalmente não há nenhuma diferença de desempenho entre uma instrução que inclui uma subconsulta e uma versão equivalente semanticamente que não inclui. Entretanto, em alguns casos em que a existência deve ser verificada, uma junção tem um desempenho melhor. Em outros casos, a consulta aninhada deve ser processada para cada resultado da consulta externa para assegurar a eliminação de duplicatas. Em tais casos, uma abordagem de junção geraria resultados melhores. O exemplo seguinte mostra uma subconsulta SELECT e uma junção SELECT que retornam o mesmo conjunto de resultados:

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

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

Uma subconsulta aninhada na instrução SELECT externa tem os seguintes componentes:

  • Uma consulta regular SELECT incluindo os componentes regulares de lista de seleção.

  • Uma cláusula regular FROM que inclui um ou mais nomes de tabela ou de exibição.

  • Uma cláusula WHERE opcional.

  • Uma cláusula GROUP BY opcional.

  • Uma cláusula HAVING opcional.

A consulta SELECT de uma subconsulta sempre é inclusa em parênteses. Não pode incluir uma cláusula COMPUTE ou FOR BROWSE, mas pode incluir apenas uma cláusula ORDER BY quando uma cláusula TOP também for especificada.

Uma subconsulta pode ser aninhada na cláusula WHERE ou HAVING de uma instrução externa SELECT, INSERT, UPDATE ou DELETE ou em outra subconsulta. Até 32 níveis de aninhamento são possíveis, embora o limite varie com base na memória disponível e na complexidade de outras expressões da consulta. É possível que consultas individuais não ofereçam suporte a aninhamento até 32 níveis. Uma subconsulta pode aparecer em qualquer lugar em que uma expressão possa ser usada, se retornar um único valor.

Se uma tabela só aparecer em uma subconsulta e não na consulta externa, então não poderão ser incluídas colunas dessa tabela na saída (a lista de seleção da consulta externa).

Instruções que incluem uma subconsulta normalmente têm um destes formatos:

  • WHERE expression [NOT] IN (subquery)

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

  • WHERE [NOT] EXISTS (subquery)

Em algumas instruções Transact-SQL, a subconsulta pode ser avaliada como se fosse uma consulta independente. Conceitualmente, os resultados da subconsulta são substituídos na consulta externa (embora isso necessariamente não seja como o Microsoft SQL Server processa de fato instruções Transact-SQL com subconsultas).

Há três tipos básicos de subconsultas. Aquelas que:

  • Funcionam em listas introduzidas com IN, ou aquelas em que um operador de comparação modificou por ANY ou ALL.

  • São introduzidas com um operador de comparação inalterado e devem retornar um único valor.

  • São testes de existência introduzidos com EXISTS.