Examine a instrução SELECT

Concluído

Transact-SQL ou T-SQL, é um dialeto da linguagem SQL padrão ANSI usada por produtos e serviços Microsoft SQL. É semelhante ao SQL padrão. A maior parte do nosso foco será na declaração SELECT, que tem de longe a maioria das opções e variações de qualquer declaração DML.

Vamos começar dando uma olhada de alto nível em como uma instrução SELECT é processada. A ordem na qual uma instrução SELECT é gravada não é a ordem na qual ela é avaliada e processada pelo mecanismo de banco de dados do SQL Server.

Considere a seguinte consulta:

SELECT OrderDate, COUNT(OrderID) AS Orders
FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate
HAVING COUNT(OrderID) > 1
ORDER BY OrderDate DESC;

A consulta consiste em uma instrução SELECT, que é composta por várias cláusulas, cada uma das quais define uma operação específica que deve ser aplicada aos dados que estão sendo recuperados. Antes de examinarmos a ordem de tempo de execução das operações, vamos dar uma olhada breve no que essa consulta faz, embora os detalhes das várias cláusulas não sejam abordados neste módulo.

A cláusula SELECT retorna a coluna OrderDate e a contagem de valores OrderID , à qual atribui o nome (ou alias) Orders:

SELECT OrderDate, COUNT(OrderID) AS Orders

A cláusula FROM identifica qual tabela é a fonte das linhas para a consulta; neste caso, é a tabela Sales.SalesOrder :

FROM Sales.SalesOrder

A cláusula WHERE filtra as linhas dos resultados, mantendo apenas as linhas que satisfazem a condição especificada; Neste caso, as encomendas que têm o estatuto de "expedidas":

WHERE Status = 'Shipped'

A cláusula GROUP BY pega as linhas que atenderam à condição de filtro e as agrupa por OrderDate, de modo que todas as linhas com a mesma OrderDate sejam consideradas como um único grupo e uma linha seja retornada para cada grupo:

GROUP BY OrderDate

Depois que os grupos são formados, a cláusula HAVING filtra os grupos com base em seu próprio predicado. Apenas as datas com mais do que uma encomenda serão incluídas nos resultados:

HAVING COUNT(OrderID) > 1

Para fins de visualização desta consulta, a cláusula final é a ORDER BY, que classifica a saída em ordem decrescente de OrderDate:

ORDER BY OrderDate DESC;

Agora que você já viu o que cada cláusula faz, vamos ver a ordem em que o SQL Server realmente as avalia:

  1. A cláusula FROM é avaliada primeiro, para fornecer as linhas de origem para o resto da instrução. Uma tabela virtual é criada e passada para a próxima etapa.
  2. A cláusula WHERE está próxima a ser avaliada, filtrando as linhas da tabela de origem que correspondem a um predicado. A tabela virtual filtrada é passada para a próxima etapa.
  3. GROUP BY é o próximo, organizando as linhas na tabela virtual de acordo com valores exclusivos encontrados na lista GROUP BY. Uma nova tabela virtual é criada, contendo a lista de grupos, e é passada para a próxima etapa. A partir deste ponto do fluxo de operações, apenas as colunas na lista GROUP BY ou funções agregadas podem ser referenciadas por outros elementos.
  4. A cláusula HAVING é avaliada em seguida, filtrando grupos inteiros com base em seu predicado. A tabela virtual criada na etapa 3 é filtrada e passada para a próxima etapa.
  5. A cláusula SELECT finalmente é executada, determinando quais colunas aparecerão nos resultados da consulta. Como a cláusula SELECT é avaliada após as outras etapas, quaisquer aliases de coluna (em nosso exemplo, Orders) criados lá não podem ser usados na cláusula GROUP BY ou HAVENDO.
  6. A cláusula ORDER BY é a última a ser executada, classificando as linhas conforme determinado por sua lista de colunas.

Para aplicar esse entendimento à nossa consulta de exemplo, aqui está a ordem lógica em tempo de execução da instrução SELECT acima:

FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate 
HAVING COUNT(OrderID) > 1
SELECT OrderDate, COUNT(OrderID) AS Orders
ORDER BY OrderDate DESC;

Nem todas as cláusulas possíveis são necessárias em todas as instruções SELECT que você escreve. A única cláusula necessária é a cláusula SELECT, que pode ser usada sozinha em alguns casos. Normalmente, uma cláusula FROM também é incluída para identificar a tabela que está sendo consultada. Além disso, o Transact-SQL tem outras cláusulas que podem ser adicionadas.

Como você viu, você não escreve consultas T-SQL na mesma ordem em que elas são logicamente avaliadas. A ordem de avaliação em tempo de execução determina quais dados estão disponíveis para quais cláusulas, pois uma cláusula só tem acesso a informações já disponibilizadas a partir de uma cláusula já processada. Por esse motivo, é importante entender a verdadeira ordem lógica de processamento ao escrever consultas.

Seleção de todas as colunas

A cláusula SELECT é frequentemente chamada de lista SELECT, porque lista os valores a serem retornados nos resultados da consulta.

A forma mais simples de uma cláusula SELECT é o uso do caractere de asterisco (*) para retornar todas as colunas. Quando usado em consultas T-SQL, é chamado de estrela. Embora o SELECT * seja adequado para um teste rápido, você deve evitar usá-lo no trabalho de produção pelos seguintes motivos:

  • As alterações na tabela que adicionam ou reorganizam colunas serão refletidas nos resultados da consulta, o que pode resultar em saída inesperada para aplicativos ou relatórios que usam a consulta.
  • O retorno de dados que não são necessários pode tornar suas consultas mais lentas e causar problemas de desempenho se a tabela de origem contiver um grande número de linhas.

Por exemplo, o exemplo a seguir recupera todas as colunas da tabela (hipotética) Production.Product .

SELECT * FROM Production.Product;

O resultado dessa consulta é um conjunto de linhas que contém todas as colunas de todas as linhas da tabela, que pode ter esta aparência:

ID do Produto

Nome

Número do Produto

Cor

Custo padrão

PreçoListado

Tamanho

Espessura

ProductCatID

680

HL Road Frame - Preto, 58

FR-R92B-58

Preto

1059.31

1431.5

58

1016.04

18

706

HL Road Frame - Vermelho, 58

FR-R92R-58

Vermelho

1059.31

1431.5

58

1016.04

18

707

Capacete Sport-100, Vermelho

HL-U509-R

Vermelho

13.0863

34.99

35

708

Capacete Sport-100, Preto

HL-U509

Preto

13.0863

34.99

35

...

...

...

...

...

...

...

...

...

Seleção de colunas específicas

Uma lista de colunas explícita permite que você tenha controle sobre exatamente quais colunas são retornadas e em que ordem. Cada coluna no resultado terá o nome da coluna como cabeçalho.

Por exemplo, considere a seguinte consulta; que novamente usa a tabela hipotética Production.Product .

SELECT ProductID, Name, ListPrice, StandardCost
‎FROM Production.Product;

Desta vez, os resultados incluem apenas as colunas especificadas:

ID do Produto

Nome

PreçoListado

Custo padrão

680

HL Road Frame - Preto, 58

1431.5

1059.31

706

HL Road Frame - Vermelho, 58

1431.5

1059.31

707

Capacete Sport-100, Vermelho

34.99

13.0863

708

Capacete Sport-100, Preto

34.99

13.0863

...

...

...

...

Seleção de expressões

Além de recuperar colunas armazenadas na tabela especificada, uma cláusula SELECT pode executar cálculos e manipulações, que usam operadores para combinar colunas e valores ou várias colunas. O resultado do cálculo ou manipulação deve ser um resultado de valor único (escalar) que aparecerá no resultado como uma coluna separada.

Por exemplo, a consulta a seguir inclui duas expressões:

SELECT ProductID,
      Name + '(' + ProductNumber + ')',
  ListPrice - StandardCost
FROM Production.Product;

Os resultados dessa consulta podem ter esta aparência:

ID do Produto

680

HL Road Frame - Preto, 58(FR-R92B-58)

372.19

706

HL Road Frame - Vermelho, 58 (FR-R92R-58)

372.19

707

Capacete Sport-100, Vermelho (HL-U509-R)

21.9037

708

Capacete Sport-100, Preto (HL-U509)

21.9037

...

...

...

Há algumas coisas interessantes a observar sobre esses resultados:

  • As colunas retornadas pelas duas expressões não têm nomes de coluna. Dependendo da ferramenta que você está usando para enviar sua consulta, um nome de coluna ausente pode ser indicado por um cabeçalho de coluna em branco, um indicador literal "sem nome de coluna" ou um nome padrão como coluna1. Veremos como especificar um alias para o nome da coluna na consulta mais adiante nesta seção.
  • A primeira expressão usa o + operador para concatenar valores de cadeia de caracteres (baseados em caracteres), enquanto a segunda expressão usa o - operador para subtrair um valor numérico de outro. Quando usado com valores numéricos, o operador executa a + adição. Claramente, então, é importante entender os tipos de dados das colunas que você inclui nas expressões. Discutiremos os tipos de dados na próxima seção.

Especificando aliases de coluna

Você pode especificar um alias para cada coluna retornada pela consulta SELECT, como alternativa ao nome da coluna de origem ou para atribuir um nome à saída de uma expressão.

Por exemplo, aqui está a mesma consulta de antes, mas com aliases especificados para cada uma das colunas:

SELECT ProductID AS ID,
      Name + '(' + ProductNumber + ')' AS ProductName,
  ListPrice - StandardCost AS Markup
FROM Production.Product;

Os resultados desta consulta incluem os nomes de coluna especificados:

ID

Nome do Produto

Margem de lucro

680

HL Road Frame - Preto, 58(FR-R92B-58)

372.19

706

HL Road Frame - Vermelho, 58 (FR-R92R-58)

372.19

707

Capacete Sport-100, Vermelho (HL-U509-R)

21.9037

708

Capacete Sport-100, Preto (HL-U509)

21.9037

...

...

...

Nota

A palavra-chave AS é opcional ao especificar um alias, mas é uma boa prática incluí-la para esclarecimento.

Formatar consultas

Você pode observar a partir dos exemplos nesta seção que você pode ser flexível sobre como formatar seu código de consulta. Por exemplo, você pode escrever cada cláusula (ou a consulta inteira) em uma única linha ou dividi-la em várias linhas. Na maioria dos sistemas de banco de dados, o código não diferencia maiúsculas de minúsculas, e alguns elementos da linguagem T-SQL são opcionais (incluindo a palavra-chave AS, como mencionado anteriormente, e até mesmo o ponto-e-vírgula no final de uma instrução).

Considere as seguintes diretrizes para tornar seu código T-SQL facilmente legível (e, portanto, mais fácil de entender e depurar!):

  • Capitalize palavras-chave T-SQL, como SELECT, FROM, AS e assim por diante. Capitalizar palavras-chave é uma convenção comumente usada que torna mais fácil encontrar cada cláusula de uma instrução complexa.
  • Inicie uma nova linha para cada cláusula principal de uma instrução.
  • Se a lista SELECT contiver mais do que algumas colunas, expressões ou aliases, considere listar cada coluna em sua própria linha.
  • Recuar linhas contendo subcláusulas ou colunas para deixar claro qual código pertence a cada cláusula principal.