Treinamento para consultas com SQL Server - Parte 7 - Sub Consultas (SUBQUERIES)

Este é um recurso muito útil na linguagem SQL permitindo colocar o resultado de consultas inteiras em uma coluna fazendo parte das linhas de uma consulta maior. Uma consulta pode ter quantas sub consultas forem necessárias, mas, existem alguns pontos de atenção:

  • O resultado da sub consulta deve ser sempre escalar, ou seja, um valor único, nunca um conjunto de linhas e colunas (rowset). Pode ser necessário usar a cláusula TOP em alguns casos.
  • Para evitar problemas, a sub consulta deve estar amarrada com alguma coluna da consulta principal.
  • Verificar os índices das tabelas envolvidas se estão apropriados. As sub consultas têm um custo muito alto de processamento e afetam em muito o desempenho caso sejam muito complexas.

Para exemplificar vamos considerar as tabelas PERSON.PERSON, SALES.SALESORDERHEADER – armazena informações sobre vendas e SALES.CUSTOMER – Clientes para o qual a venda foi feita. O diagrama de relacionamentos pode ser conferido a seguir.

O objetivo é ter o resultado da somatória do total das vendas (SALES.SALESORDERHEADER.TotalDue) dos anos 2005 a 2007 agrupados por nome de cliente (PERSON.PERSON.FirstName e PERSON,PERSON.LastName). A instrução SQL para executar isto, trabalhando com sub consultas está demonstrada a seguir.

select concat(p.FirstName, ' ', p.LastName) as CompleteName
 ,(
  select isnull(sum(soh.TotalDue), 0) as TotalVenda
  from Sales.SalesOrderHeader soh
  join Sales.Customer cus on cus.CustomerID=soh.CustomerID
  join person.Person per on per.BusinessEntityID=cus.PersonID
  where per.BusinessEntityID=p.BusinessEntityID
   and year(OrderDate)=2005
 ) as [2005]
 ,(
  select isnull(sum(soh.TotalDue), 0) as TotalVenda
  from Sales.SalesOrderHeader soh
  join Sales.Customer cus on cus.CustomerID=soh.CustomerID
  join person.Person per on per.BusinessEntityID=cus.PersonID
  where per.BusinessEntityID=p.BusinessEntityID
   and year(OrderDate)=2006
 ) as [2006]
 ,(
  select isnull(sum(soh.TotalDue), 0) as TotalVenda
  from Sales.SalesOrderHeader soh
  join Sales.Customer cus on cus.CustomerID=soh.CustomerID
  join person.Person per on per.BusinessEntityID=cus.PersonID
  where per.BusinessEntityID=p.BusinessEntityID
   and year(OrderDate)=2007
 ) as [2007]
from Person.Person p

No exemplo, note que está sendo usada a função CONCAT(). Esta permite concatenar dados do tipo string (ou nvarchar, ou varchar...) de forma mais eficiente e organizada do que simplesmente usar o operador “+”. É importante observar que esta função só está disponível a partir da versão 2012 do SQL Server.

Cada sub consulta além de possuir suas joins e cláusulas de filtros próprias também está ligada com a tabela principal PERSON.PERSON através da seguinte linha:

  where per.BusinessEntityID=p.BusinessEntityID

que está presente nas três sub consultas. O resultado desta consulta pode ser conferido a seguir.

Outros bons artigos sobre sub consultas podem ser conferidos nos links abaixo:

  1. Noções básicas sobre subconsultas - Technet/Microsoft
  2. Subqueries in SQL Server - Simple Talk