You are on page 1of 41

SELECT

Recupera linhas do banco de dados e permite a seleção de uma ou várias linhas ou colunas de uma ou
várias tabelas no SQL Server. A sintaxe completa da instrução SELECT é complexa, mas as cláusulas
principais podem ser assim resumidas:

[ WITH { [ XMLNAMESPACES ,] [ <common_table_expression> ] } ]

SELECT select_list [ INTO new_table ]

[ FROM table_source ] [ WHERE search_condition ]

[ GROUP BY group_by_expression ]

[ HAVING search_condition ]

[ ORDER BY order_expression [ ASC | DESC ] ]

Os operadores UNION, EXCEPT e INTERSECT podem ser usados entre consultas para combinar ou
comparar os resultados em um único conjunto de resultados.

Sintaxe

SQL
-- Syntax for SQL Server and Azure SQL Database

<SELECT statement> ::=


[ WITH { [ XMLNAMESPACES ,] [ <common_table_expression> [,...n] ] } ]
<query_expression>
[ ORDER BY { order_by_expression | column_position [ ASC | DESC ] }
[ ,...n ] ]
[ <FOR Clause>]
[ OPTION ( <query_hint> [ ,...n ] ) ]
<query_expression> ::=
{ <query_specification> | ( <query_expression> ) }
[ { UNION [ ALL ] | EXCEPT | INTERSECT }
<query_specification> | ( <query_expression> ) [...n ] ]
<query_specification> ::=
SELECT [ ALL | DISTINCT ]
[TOP ( expression ) [PERCENT] [ WITH TIES ] ]
< select_list >
[ INTO new_table ]
[ FROM { <table_source> } [ ,...n ] ]
[ WHERE <search_condition> ]
[ <GROUP BY> ]
[ HAVING < search_condition > ]

Remarks

Devido à complexidade da instrução SELECT, os elementos e argumentos de sintaxe detalhados


são mostrados por cláusula:

 WITH XMLNAMESPACES  HAVING


 WITH common_table_expression  UNION
 Cláusula SELECT  EXCEPT e INTERSECT
 Cláusula INTO  ORDER BY

1
 FROM  Cláusula FOR
 WHERE  Cláusula OPTION
 GROUP BY

A ordem das cláusulas na instrução SELECT é significativa. Qualquer uma das cláusulas opcionais
pode ser omitida, mas quando elas são usadas devem aparecer na ordem apropriada.

As instruções SELECT serão permitidas em funções definidas pelo usuário apenas se as listas de
seleção dessas instruções contiverem expressões que atribuam valores a variáveis que são locais a
essas funções.

Um nome de quatro partes construído com a função OPENDATASOURCE como a parte do nome
do servidor pode ser usado como uma origem de tabela sempre que um nome de tabela puder
aparecer em uma instrução SELECT. Um nome de quatro partes não pode ser especificado para Banco
de dados SQL do Azure.

Algumas restrições de sintaxe se aplicam a instruções SELECT que envolvem tabelas remotas.

Ordem de processamento lógico da instrução SELECT

As etapas a seguir mostram a ordem de processamento lógico ou a ordem de associação de uma


instrução SELECT. Essa ordem determina quando os objetos definidos em uma etapa são
disponibilizados para as cláusulas em etapas subsequentes. Por exemplo, se o processador de consulta
puder ser associado (acessar) a tabelas ou exibições definidas na cláusula FROM, esses objetos e suas
colunas serão disponibilizados para todas as etapas subsequentes. De modo oposto, como a cláusula
SELECT é a etapa 8, qualquer alias de coluna ou coluna derivada definida naquela cláusula não poderá
ser referenciada por cláusulas precedentes. Porém, poderão ser referenciadas por cláusulas
subsequentes, como a cláusula ORDER BY. A execução física real da instrução é determinada pelo
processador de consulta e a ordem pode variar com base nesta lista.

1. FROM 7. HAVING
2. ON 8. SELECT
3. JOIN 9. DISTINCT
4. WHERE 10. ORDER BY
5. GROUP BY 11. INICIO
6. WITH CUBE ou WITH ROLLUP

Aviso
A sequência anterior geralmente é verdadeira. No entanto, há casos incomuns em que a sequência
pode ser diferente.
Por exemplo, suponha que você tenha um índice clusterizado em uma exibição e a exibição exclui
algumas linhas de tabela e lista de colunas SELECT da exibição usa um CONVERT que altera um tipo de
dados de varchar para integer. Nessa situação, CONVERT pode ser executado antes da execução da
cláusula WHERE. Isso é um tanto incomum. Geralmente, há uma maneira de modificar a exibição para
evitar a sequência diferente, se isso é importante em seu caso.

2
Permissões

A seleção de dados exige a permissão SELECT na tabela ou exibição, que pode ser herdada de um escopo
superior, como a permissão SELECT no esquema ou a permissão CONTROL na tabela.Ou exige a associação à
função de banco de dados fixa db_datareader ou db_owner ou à função de servidor fixa sysadmin. A
criação de uma nova tabela com SELECTINTO também exige a permissão CREATETABLE e a
permissão ALTERSCHEMA no esquema que possui a nova tabela.

Exemplos:

O exemplo a seguir usa o banco de dados AdventureWorksPDW2012.

A. Usando SELECT para recuperar linhas e colunas

Esta seção mostra três exemplos de código. Este primeiro exemplo de código retorna todas as
linhas (nenhuma cláusula WHERE foi especificada) e todas as colunas (usando o *) da
tabela DimEmployee.

SQL
SELECT *
FROM DimEmployee
ORDER BY LastName;

Este próximo exemplo usa a definição de alias da tabela para obter o mesmo resultado.

SQL
SELECT e.*
FROM DimEmployee AS e
ORDER BY LastName;

Este exemplo retorna todas as linhas (nenhuma cláusula WHERE foi especificada) e um subconjunto das
colunas (FirstName, LastName, StartDate) da tabela DimEmployee no banco de
dados AdventureWorksPDW2012. O terceiro título de coluna é renomeado como FirstDay.

SQL
SELECT FirstName, LastName, StartDate AS FirstDay
FROM DimEmployee
ORDER BY LastName;

Este exemplo retorna somente as linhas de DimEmployee que têm uma EndDate que não é NULL e
um MaritalStatus igual a 'M' (married, casado).

SQL
SELECT FirstName, LastName, StartDate AS FirstDay
FROM DimEmployee
WHERE EndDate IS NOT NULL
AND MaritalStatus = 'M'
ORDER BY LastName;

b. Usando SELECT com títulos de coluna e cálculos

3
O exemplo a seguir retorna todas as linhas da tabela DimEmployee e calcula o pagamento bruto de cada
funcionário com base em sua BaseRate e em uma semana de trabalho de 40 horas.

SQL
SELECT FirstName, LastName, BaseRate, BaseRate * 40 AS GrossPay
FROM DimEmployee
ORDER BY LastName;

C. Usando DISTINCT com SELECT

O exemplo a seguir usa DISTINCT para gerar uma lista de todos os títulos exclusivos na tabela DimEmployee.

SQL
SELECT DISTINCT Title
FROM DimEmployee
ORDER BY Title;
D. Usando GROUP BY

O exemplo a seguir localiza a quantidade total de todas as vendas em cada dia.

SQL
SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey
ORDER BY OrderDateKey;
Devido à cláusula GROUP BY, somente uma linha que contém a soma de todas as vendas é retornada para
cada dia.

E. Usando GROUP BY com vários grupos

O exemplo a seguir localiza o preço médio e a soma de vendas pela Internet de cada dia, agrupados por data
do pedido e código promocional.

SQL
SELECT OrderDateKey, PromotionKey, AVG(SalesAmount) AS AvgSales,
SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey, PromotionKey
ORDER BY OrderDateKey;

F. Usando GROUP BY e WHERE

O exemplo a seguir põe os resultados em grupos depois de recuperar apenas as linhas com datas de pedido
posteriores a 1º de agosto de 2002.

SQL
SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
WHERE OrderDateKey > '20020801'
GROUP BY OrderDateKey
ORDER BY OrderDateKey;

4
G. Usando GROUP BY com uma expressão

O exemplo a seguir agrupa por uma expressão. É possível agrupar por uma expressão se a mesma não
contiver funções de agregação.

SQL
SELECT SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY (OrderDateKey * 10);

H. Usando GROUP BY com ORDER BY

O exemplo a seguir localiza a soma de vendas por dia e os pedidos por dia.

SQL
SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey
ORDER BY OrderDateKey;

I. Usando a cláusula HAVING

Essa consulta usa a cláusula HAVING para restringir os resultados.

SQL
SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey
HAVING OrderDateKey > 20010000
ORDER BY OrderDateKey;

SELECT – Cláusula INTO


SELECT…INTO cria uma tabela no grupo de arquivos padrão e insere nela as linhas resultantes da consulta.

Sintaxe

SQL
[ INTO new_table ]
[ ON filegroup ]

Argumentos

new_table

Especifica o nome de uma nova tabela a ser criada com base nas colunas da lista de seleção e nas
linhas escolhidas na origem dos dados.

O formato de new_table é determinado pela avaliação das expressões na lista de seleção. As colunas
na new_table são criadas na ordem especificada pela lista de seleção. Cada coluna em new_table tem o
mesmo nome, tipo de dados, nulidade e valor que a expressão correspondente na lista de seleção. A

5
propriedade IDENTITY de uma coluna é transferida, exceto nas condições definidas em "Trabalhando
com colunas de identidade", na seção Comentários.

Para criar a tabela em outro banco de dados na mesma instância do SQL Server, especifique
new_table como um nome totalmente qualificado no formato database.schema.table_name.

Não é possível criar new_table em um servidor remoto. No entanto, você pode popular
new_table de uma fonte de dados remota. Para criar new_table de uma tabela de origem remota,
especifique a tabela de origem usando um nome de quatro partes no formato
linked_server.catálogo.esquema.objeto na cláusula FROM da instrução SELECT. Como alternativa, é
possível usar a função OPENQUERY ou a função OPENDATASOURCE na cláusula FROM para especificar
a fonte de dados remota.

filegroup

Especifica o nome do grupo de arquivos no qual a nova tabela será criada. O grupo de arquivos
especificado deverá existir no banco de dados, caso contrário, o mecanismo do SQL Server gerará um
erro.

Tipos de dados

O atributo FILESTREAM não é transferido para a nova tabela. Os BLOBs do FILESTREAM são
copiados e armazenados na nova tabela como BLOBs varbinary(max) . Sem o atributo FILESTREAM, o
tipo de dados varbinary(max) tem uma limitação de 2 GB. Se um FILESTREAM BLOB exceder esse valor,
ocorrerá o erro 7119, e a instrução será interrompida.

Quando uma coluna de identidade existente é seleciona para uma nova tabela, a nova coluna
herda a propriedade IDENTITY, a menos que uma das seguintes condições seja verdadeira:

 A instrução SELECT contém uma junção.


 Várias instruções SELECT são unidas usando UNION.
 A coluna de identidade é listada mais de uma vez na lista de seleção.
 A coluna de identidade faz parte de uma expressão.
 A coluna de identidade provém de uma fonte de dados remota.

Se alguma dessas condições for verdadeira, a coluna será criada como NOT NULL em vez de
herdar a propriedade IDENTITY. Se uma coluna de identidade for obrigatória na nova tabela, mas não
estiver disponível, ou se você desejar um valor de semente ou de incremento diferente da coluna de
identidade de origem, defina a coluna na lista de seleção que usa a função IDENTITY. Consulte "Criando
uma coluna de identidade usando a função IDENTITY" na seção Exemplos abaixo.

Remarks

A instrução SELECT...INTO opera em duas partes – a nova tabela é criada e, em seguida, as linhas
são inseridas. Isso significa que, se as inserções falharem, elas serão todas revertidas, mas a nova
tabela (vazia) permanecerá. Se você precisar que toda a operação tenha êxito ou falhe como um todo,
use uma transação explícita.

Limitações e Restrições

Não é possível especificar uma variável de tabela ou um parâmetro com valor de tabela como a
nova tabela.

6
Você não pode usar SELECT...INTO para criar uma tabela particionada, mesmo quando a tabela de
origem está particionada. SELECT...INTO não usa o esquema de partição da tabela de origem; em vez
disso, a nova tabela é criada no grupo de arquivos padrão. Para inserir linhas em uma tabela
particionada, crie primeiro a tabela particionada e depois use a instrução INSERT
INTO...SELECT...FROM.

Índices, restrições e gatilhos definidos na tabela de origem não são transferidos para a nova
tabela, nem podem ser especificados na instrução SELECT...INTO. Se esses objetos forem obrigatórios,
você poderá criá-los depois de executar a instrução SELECT...INTO.

Especificar uma cláusula ORDER BY não garante que as linhas sejam inseridas na ordem
especificada.

Quando uma coluna esparsa é incluída na lista de seleção, a propriedade da coluna esparsa não é
transferida para a coluna na nova tabela. Se essa propriedade for necessária na nova tabela, altere a
definição de coluna depois de executar a instrução SELECT... INTO para incluir essa propriedade.

Quando uma coluna computada é incluída na lista de seleção, a coluna correspondente na nova
tabela não é uma coluna computada. Os valores na nova coluna são os que foram calculados no
momento em que a SELECT...INTO foi executada.

Comportamento de log

A quantidade de registro em log para SELECT...INTO depende do modelo de recuperação em vigor


para o banco de dados. Nos modelos de recuperação simples ou bulk-logged, as operações em massa
são registradas minimamente. Com o log mínimo, usar a instrução SELECT...INTO pode ser mais
eficiente do que criar uma tabela e então preenchê-la usando uma instrução INSERT. Para obter mais
informações, consulte O log de transações (SQL Server).

Permissões

Exige permissão CREATE DATABASE no banco de dados de destino.

SELECT – HAVING
Especifica um critério de pesquisa para um grupo ou uma agregação. HAVING pode ser usado
somente com a instrução SELECT. HAVING é normalmente usado com uma cláusula GROUP BY.
Quando GROUP BY não for usado, haverá um único grupo agregado e implícito.

Sintaxe

SQL
[ HAVING <search condition> ]

<search_condition> especifica um ou mais predicados aos quais os grupos e/ou as agregações devem
corresponder.

Os tipos de dados text, image e ntext não podem ser usados em uma cláusula HAVING.

Exemplos

O exemplo a seguir que usa uma cláusula simples HAVING recupera o total para cada SalesOrderID da
tabela SalesOrderDetail que excede $100000.00.

7
SQL
USE AdventureWorks2012 ;
GO
SELECT SalesOrderID, SUM(LineTotal) AS SubTotal
FROM Sales.SalesOrderDetail
GROUP BY SalesOrderID
HAVING SUM(LineTotal) > 100000.00
ORDER BY SalesOrderID ;

SELECT – GROUP BY

Uma cláusula da instrução SELECT que divide o resultado da consulta em grupos de linhas,
normalmente, com a finalidade de executar uma ou mais agregações em cada grupo. A instrução
SELECT retorna uma linha por grupo.

Sintaxe

SQL
-- Syntax for SQL Server and Azure SQL Database
-- ISO-Compliant Syntax

GROUP BY {
column-expression
| ROLLUP ( <group_by_expression> [ ,...n ] )
| CUBE ( <group_by_expression> [ ,...n ] )
| GROUPING SETS ( <grouping_set> [ ,...n ] )
| () --calculates the grand total
} [ ,...n ]

<group_by_expression> ::=
column-expression
| ( column-expression [ ,...n ] )

<grouping_set> ::=
() --calculates the grand total
| <grouping_set_item>
| ( <grouping_set_item> [ ,...n ] )

<grouping_set_item> ::=
<group_by_expression>
| ROLLUP ( <group_by_expression> [ ,...n ] )
| CUBE ( <group_by_expression> [ ,...n ] )

-- For backward compatibility only.


-- Non-ISO-Compliant Syntax for SQL Server and Azure SQL Database

GROUP BY
[ ALL ] column-expression [ ,...n ]
| column-expression [ ,...n ] [ WITH { CUBE | ROLLUP } ]

8
Argumentos

column-expression

Especifica uma coluna ou um cálculo de não agregação em uma coluna. Essa coluna pode
pertencer a uma tabela, a uma tabela derivada ou a uma exibição. A coluna precisa aparecer na
cláusula FROM da instrução SELECT, mas não precisa aparecer na lista de SELECT.

A coluna precisa aparecer na cláusula FROM da instrução SELECT, mas não precisa aparecer na
lista de SELECT. No entanto, cada coluna de tabela ou de exibição em qualquer expressão de não
agregação na lista de <select> precisa estar incluída na lista de GROUP BY:

As seguintes instruções são permitidas:

SQL
SELECT ColumnA, ColumnB FROM T GROUP BY ColumnA, ColumnB;
SELECT ColumnA + ColumnB FROM T GROUP BY ColumnA, ColumnB;
SELECT ColumnA + ColumnB FROM T GROUP BY ColumnA + ColumnB;
SELECT ColumnA + ColumnB + constant FROM T GROUP BY ColumnA, ColumnB;

As seguintes instruções não são permitidas:

SQL
SELECT ColumnA, ColumnB FROM T GROUP BY ColumnA + ColumnB;
SELECT ColumnA + constant + ColumnB FROM T GROUP BY ColumnA + ColumnB;

A expressão de coluna não pode conter:

 Um alias de coluna definido na lista de SELECT. Ela pode usar um alias de coluna para uma tabela
derivada definida na cláusula FROM.
 Uma coluna do tipo text, ntext ou image. No entanto, você pode usar uma coluna de texto, ntext
ou imagem como um argumento para uma função que retorna um valor de um tipo de dados
válido. Por exemplo, a expressão pode usar SUBSTRING() e CAST(). Isso também se aplica às
expressões na cláusula HAVING.
 Métodos do tipo de dados XML. Ela pode incluir uma função definida pelo usuário que usa
métodos do tipo de dados XML. Ela pode incluir uma coluna computada que usa métodos do tipo
de dados XML.
 Uma subconsulta. O erro 144 é retornado.
 Uma coluna de uma exibição indexada.

GROUP BY column-expression [ ,...n ]

Agrupa os resultados da instrução SELECT de acordo com os valores em uma lista de uma ou mais
expressões de coluna.

Por exemplo, essa consulta cria a tabela Vendas com as colunas País, Região e Vendas. Ela insere
quatro linhas e duas das linhas têm valores correspondentes para País e Região.

9
SQL
CREATE TABLE Sales ( Country varchar(50), Region varchar(50), Sales int );

INSERT INTO sales VALUES (N'Canada', N'Alberta', 100);


INSERT INTO sales VALUES (N'Canada', N'British Columbia', 200);
INSERT INTO sales VALUES (N'Canada', N'British Columbia', 300);
INSERT INTO sales VALUES (N'United States', N'Montana', 100);

A tabela Vendas contém estas linhas:

Região
País Sales
Alberta
Canada 100
Colúmbia Britânica
Canada 200
Colúmbia Britânica
Canada 300
Estados Unidos
Montana 100

Essa próxima consulta agrupa País e Região e retorna a soma de agregação para cada combinação
de valores.

SQL
SELECT Country, Region, SUM(sales) AS TotalSales
FROM Sales
GROUP BY Country, Region;

O resultado da consulta tem 3 linhas, pois há 3 combinações de valores para País e


Região.TotalSales para Canadá e Colúmbia Britânica é a soma de duas linhas.

Região
País Sales
Alberta
Canada 100
Colúmbia Britânica
Canada 500
Estados Unidos
Montana 100
GROUP BY ROLLUP

Cria um grupo para cada combinação de expressões de coluna. Além disso, ele "acumula" os resultados
em subtotais e totais gerais. Para isso, ele vai da direita para a esquerda, diminuindo o número de
expressões de coluna sobre as quais ele cria grupos e agregações.

A ordem da coluna afeta a saída de ROLLUP e pode afetar o número de linhas no conjunto de
resultados.

10
Por exemplo, GROUP BY ROLLUP (col1, col2, col3, col4) cria grupos para cada combinação de
expressões de coluna nas listas a seguir.

 col1, col2, col3, col4


 col1, col2, col3, NULL
 col1, col2, NULL, NULL
 col1, NULL, NULL, NULL
 NULL, NULL, NULL, NULL – esse é o total geral

Usando a tabela do exemplo anterior, esse código executa uma operação de GROUP BY ROLLUP em
vez de um GROUP BY simples.

SQL
SELECT Country, Region, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY ROLLUP (Country, Region);

O resultado da consulta tem as mesmas agregações que o GROUP BY simples sem o ROLLUP.Além
disso, ele cria subtotais para cada valor de País. Por fim, ele fornece um total geral para todas as linhas. O
resultado será semelhante a este:

Região
País Sales
Alberta
Canada 100
Colúmbia Britânica
Canada 500
NULL
Canada 600
Estados Unidos
Montana 100
Estados Unidos
NULL 100

NULL NULL 700

GROUP BY CUBE ( )

GROUP BY CUBE cria grupos para todas as combinações de colunas possíveis. GROUP BY CUBE (a, b) os
resultados têm grupos de valores exclusivos de (a, b), (NULL, b), (a, NULL) e (NULL, NULL).

Usando a tabela dos exemplos anteriores, esse código executa uma operação de GROUP BY CUBE em
País e em Região.

SQL
SELECT Country, Region, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY CUBE (Country, Region);

O resultado da consulta tem grupos de valores exclusivos (País, Região), (NULL, Região), (País, NULL) e
(NULL, NULL). Os resultados serão semelhantes a estes:

11
País Região Sales
Canada Alberta 100
NULL Alberta 100
Canada Colúmbia Britânica 500
NULL Colúmbia Britânica 500
Estados Unidos Montana 100
NULL Montana 100
NULL NULL 700
Canada NULL 600
Estados Unidos NULL 100

GROUP BY GROUPING SETS ( )

A opção de GROUPING SETS oferece a capacidade de combinar várias cláusulas GROUP BY em uma
única cláusula GROUP BY. Os resultados são o equivalente de UNION ALL dos grupos especificados.

Por exemplo, GROUP BY ROLLUP (Country, Region) e GROUP BY GROUPING SETS ( ROLLUP (Country,
Region) ) retornam os mesmos resultados.

Quando conjuntos de GROUPING SETS têm dois ou mais elementos, os resultados são uma união dos
elementos. Este exemplo retorna a união dos resultados de ROLLUP e CUBE para País e Região.

SQL
SELECT Country, Region, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY GROUPING SETS ( ROLLUP (Country, Region), CUBE (Country, Region) );

Os resultados são iguais, pois essa consulta retorna uma união de duas instruções GROUP BY.

SQL
SELECT Country, Region, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY ROLLUP (Country, Region)
UNION ALL
SELECT Country, Region, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY CUBE (Country, Region);
O SQL não consolida grupos duplicados gerados por uma lista de GROUPING SETS. Por exemplo,
em GROUP BY ( (), CUBE (Country, Region) ), ambos os elementos retornarão uma linha para o total geral e
ambas as linhas serão listadas nos resultados.

GROUP BY ()

Especifica o grupo vazio que gera o total geral. Isso é útil como um dos elementos de um GROUPING
SET. Por exemplo, está instrução fornece o total de vendas para cada país e, em seguida, o total geral para
todos os países.

SQL
SELECT Country, SUM(Sales) AS TotalSales

12
FROM Sales
GROUP BY GROUPING SETS ( Country, () );
GROUP BY [ ALL ] column-expression [ ,...n ]

Aplica-se a: SQL Server e Banco de Dados SQL do Azure

OBSERVAÇÃO: Esta sintaxe é fornecida apenas para fins de compatibilidade com versões
anteriores. Ela será removida em uma versão futura. Evite usar essa sintaxe em novos trabalhos de
desenvolvimento e planeje modificar os aplicativos que a usam no momento.

Especifica a inclusão de todos os grupos nos resultados, independentemente se eles atendem aos
critérios de pesquisa na cláusula WHERE. Os grupos que não atendem aos critérios de pesquisa têm NULL
para a agregação.

GROUP BY ALL:

 Não é compatível com consultas que acessam tabelas remotas quando também há uma cláusula
WHERE na consulta.
 Falhará em colunas que têm o atributo FILESTREAM.

WITH (DISTRIBUTED_AGG)

Aplica-se a: SQL Data Warehouse do Azure e Parallel Data Warehouse

A dica de consulta DISTRIBUTED_AGG força o sistema de MPP (processamento paralelo massivo) a


redistribuir uma tabela em uma coluna específica antes de executar uma agregação. Somente uma coluna
na cláusula GROUP BY pode ter uma dica de consulta DISTRIBUTED_AGG. Depois que a consulta for
concluída, a tabela redistribuída será descartada. A tabela original não é alterada.

OBSERVAÇÃO: A dica de consulta DISTRIBUTED_AGG é fornecida para fins de compatibilidade com


versões anteriores do Parallel Data Warehouse e não melhora o desempenho na maioria das consultas. Por
padrão, o MPP já redistribui os dados conforme o necessário para melhorar o desempenho das agregações.

Comentários gerais

Como GROUP BY interage com a instrução SELECT

Lista de SELECT:

 Agregações de vetor. Se funções de agregação são incluídas na lista de SELECT, GROUP BY calcula
um valor resumido para cada grupo. São conhecidas como agregações de vetor.
 Agregações de distinção. As agregações AVG (DISTINCT column_name), COUNT (DISTINCT
column_name) e SUM (DISTINCT column_name) são compatíveis com ROLLUP, CUBE e
GROUPING SETS.

Cláusula WHERE:

 O SQL remove as linhas que não atendem às condições na cláusula WHERE antes que qualquer
operação de agrupamento seja executada.

Cláusula HAVING:

 O SQL usa a cláusula having para filtrar grupos no conjunto de resultados.

13
Cláusula ORDER BY:

 Use a cláusula ORDER BY para ordenar o conjunto de resultados. A cláusula GROUP BY não
ordena o conjunto de resultados.

Valores NULL:

 Se uma coluna de agrupamento contiver valores NULL, todos os valores NULL serão considerados
iguais e serão coletados em um único grupo.

Set Operators – UNION

Combina os resultados de duas ou mais consultas em um único conjunto de resultados. Esse conjunto
inclui todas as linhas que pertencem a todas as consultas na união. A operação UNION é diferente de usar
junções que combinam colunas de duas tabelas.

A seguir são apresentadas as regras básicas de combinação dos conjuntos de resultados de duas
consultas usando UNION:

 O número e a ordem das colunas devem ser iguais em todas as consultas.


 Os tipos de dados devem ser compatíveis.

Sintaxe

SQL
{ <query_specification> | ( <query_expression> ) }
{ UNION [ ALL ]
{ <query_specification> | ( <query_expression> ) }
[ ...n ] }

Argumentos

<query_specification> | ( <query_expression> ) é uma especificação de consulta ou uma expressão de


consulta que retorna dados a serem combinados com os dados de outra especificação de consulta ou
expressão de consulta. As definições das colunas que fazem parte de uma operação UNION não precisam
ser iguais, mas devem ser compatíveis por meio de conversão implícita. Quando os tipos de dados diferirem,
o tipo de dados resultante será determinado com base nas regras de precedência de tipo de dados. Quando
os tipos são iguais, mas diferem em precisão, escala ou extensão, o resultado se baseia nas mesmas regras
para combinação de expressões. Para obter mais informações, consulte Precisão, escala e comprimento
(Transact-SQL).

As colunas do tipo de dados xml precisam ser iguais. Todas as colunas devem ter tipo para um
esquema XML ou sem-tipo. Se tiverem tipo, elas deverão ter o tipo igual ao da coleção de esquema XML.

UNION
Especifica que vários conjuntos de resultados serão combinados e retornados como um único conjunto de
resultados.

14
ALL
Incorpora todas as linhas nos resultados, incluindo duplicatas. Se não for especificado, as linhas duplicadas
serão removidas.

Exemplo usando uma UNION simples

No exemplo a seguir, o conjunto de resultados inclui o conteúdo das colunas ProductModelID e Name
das tabelas ProductModel e Gloves.

SQL
-- Uses AdventureWorks

IF OBJECT_ID ('dbo.Gloves', 'U') IS NOT NULL


DROP TABLE dbo.Gloves;
GO
-- Create Gloves table.
SELECT ProductModelID, Name
INTO dbo.Gloves
FROM Production.ProductModel
WHERE ProductModelID IN (3, 4);
GO

-- Here is the simple union.


-- Uses AdventureWorks

SELECT ProductModelID, Name


FROM Production.ProductModel
WHERE ProductModelID NOT IN (3, 4)
UNION
SELECT ProductModelID, Name
FROM dbo.Gloves
ORDER BY Name;
GO

SELECT – Cláusula ORDER BY

Classifica dados retornados por uma consulta no SQL Server. Use esta cláusula para:

 Classificar o conjunto de resultados de uma consulta pela lista de colunas especificada e,


opcionalmente, limitar as linhas retornadas a um intervalo especificado. A ordem na qual as
linhas são retornadas em um conjunto de resultados não é garantida, a menos que uma cláusula
ORDER BY seja especificada.
 Determine a ordem na qual os valores da função de classificação serão aplicados ao
conjunto de resultados.

Observação
ORDER BY não é compatível com as instruções SELECT/INTO ou CREATE TABLE AS SELECT (CTAS) no
Azure SQL Data Warehouse nem no Parallel Data Warehouse.

Sintaxe

SQL

15
ORDER BY order_by_expression
[ COLLATE collation_name ]
[ ASC | DESC ]
[ ,...n ]
[ <offset_fetch> ]

<offset_fetch> ::=
{
OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }
[
FETCH { FIRST | NEXT } {integer_constant | fetch_row_count_expression } { ROW |
ROWS } ONLY
]
}

Argumentos

order_by_expression

Especifica uma coluna ou expressão na qual o conjunto de resultados da consulta deve ser
classificado. Uma coluna de classificação pode ser especificada como um nome ou alias de coluna, ou um
inteiro não negativo que representa a posição da coluna na lista de seleção.

Várias colunas de classificação podem ser especificadas. Os nomes de coluna devem ser exclusivos. A
sequência das colunas de classificação na cláusula ORDER BY define a organização do conjunto de resultados
classificado. Ou seja, o conjunto de resultados é classificado pela primeira coluna e então essa lista
ordenada é classificada pela segunda coluna e assim por diante.

Os nomes de coluna referenciados na cláusula ORDER BY devem corresponder a uma coluna ou a um


alias de coluna na lista de seleção ou a uma coluna definida em uma tabela especificada na cláusula FROM
sem nenhuma ambiguidade. Se a cláusula ORDER BY fizer referência a um alias de coluna na lista de seleção,
o alias de coluna deverá ser usado de modo autônomo, e não como parte de alguma expressão na cláusula
ORDER BY, por exemplo:

SQL
SELECT SCHEMA_NAME(schema_id) AS SchemaName FROM sys.objects
ORDER BY SchemaName; -- correct
SELECT SCHEMA_NAME(schema_id) AS SchemaName FROM sys.objects
ORDER BY SchemaName + ''; -- wrong

COLLATE collation_name

Especifica que a operação ORDER BY deve ser executada de acordo com a ordenação especificada
em collation_name e não de acordo com a ordenação da coluna definida na tabela ou na
exibição. collation_name pode ser um nome de ordenação do Windows ou um nome de ordenação
SQL. Para obter mais informações, consulte Suporte a ordenações e a Unicode.COLLATE é aplicável somente
a colunas do tipo char, varchar, nchar e nvarchar.

ASC | DESC

Define que os valores na coluna especificada devem ser classificados em ordem crescente ou
decrescente. ASC classifica do valor mais baixo para o valor mais alto. DESC classifica do valor mais alto para

16
o valor mais baixo. ASC é a ordem de classificação padrão. Valores nulos são tratados como os menores
valores possíveis.

OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }


Especifica o número de linhas que devem ser ignoradas antes de começar a retornar linhas da expressão de
consulta. O valor pode ser uma expressão ou constante inteira que seja maior que ou igual a zero.

Aplica-se a: SQL Server 2012 (11.x) até o SQL Server 2017 e o Banco de dados SQL do Azure.

offset_row_count_expression pode ser uma subconsulta escalar de constante, parâmetro ou


variável. Quando uma subconsulta é usada, ela não pode referenciar nenhuma coluna definida no escopo de
consulta externa. Ou seja, ela não pode ser correlacionada com a consulta externa.

ROW e ROWS são sinônimos fornecidos para compatibilidade ANSI.

Nos planos de execução de consulta, o valor da contagem de linhas de deslocamento é exibido no


atributo Offset do operador de consulta TOP.

FETCH { FIRST | NEXT } { integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY


Especifica o número de linhas que devem ser retornadas depois que a cláusula OFFSET for processada. O
valor pode ser uma expressão ou constante inteira que seja maior que ou igual a um.

Aplica-se a: SQL Server 2012 (11.x) a SQL Server 2017 e Banco de dados SQL do Azure.

fetch_row_count_expression pode ser uma subconsulta escalar de constante, parâmetro ou


variável. Quando uma subconsulta é usada, ela não pode referenciar nenhuma coluna definida no escopo de
consulta externa. Ou seja, ela não pode ser correlacionada com a consulta externa.

FIRST e NEXT são sinônimos fornecidos para compatibilidade ANSI.

ROW e ROWS são sinônimos fornecidos para compatibilidade ANSI.

Nos planos de execução de consulta, o valor da contagem de linhas de deslocamento é exibido no


atributo Rows ou Top do operador de consulta TOP.

Práticas recomendadas

Evite especificar inteiros na cláusula ORDER BY como representações de posição das colunas na lista de
seleção. Por exemplo, embora uma instrução como SELECT ProductID, Name FROM Production.Production
ORDER BY 2 seja válida, ela não é entendida por outros com tanta facilidade quanto com a especificação do
nome de coluna real. Além disso, as alterações na lista de seleção, como a alteração da ordem das colunas
ou a adição de novas colunas, exigirão a modificação da cláusula ORDER BY para evitar resultados
inesperados.

Em uma instrução SELECT TOP (N), sempre use uma cláusula ORDER BY. Essa é a única forma de indicar
de maneira previsível as linhas que são afetadas por TOP.

Interoperabilidade

Quando usada com uma instrução SELECT…INTO para inserir linhas de outra origem, a cláusula ORDER
BY não garante que as linhas sejam inseridas na ordem especificada.

O uso de OFFSET e FETCH em uma exibição não altera a propriedade updateability da exibição.

17
Limitações e Restrições

Não há um limite para o número de colunas na cláusula ORDER BY; porém, o tamanho total das
colunas especificado em uma cláusula ORDER BY não pode exceder 8.060 bytes.

As colunas do tipo ntext, text, image, geography, geometry e XML não podem ser usadas em uma
cláusula ORDER BY.

Nem um inteiro nem uma constante podem ser especificados quando order_by_expressionaparece em
uma função de classificação.

Se um nome de tabela tiver um alias na cláusula FROM, apenas o nome do alias poderá ser utilizado
para qualificar suas colunas na cláusula ORDER BY.

Os nomes e aliases de coluna especificados na cláusula ORDER BY deverão ser definidos na lista de
seleção, se a instrução SELECT contiver uma das seguintes cláusulas ou dos seguintes operadores:

 operador UNION
 operador EXCEPT
 operador INTERSECT
 SELECT DISTINCT

Além disso, quando a instrução incluir um operador UNION, EXCEPT ou INTERSECT, os nomes ou
aliases de coluna precisarão ser especificados na lista de seleção da primeira consulta (do lado esquerdo).

Em uma consulta que usa operadores UNION, EXCEPT ou INTERSECT, ORDER BY é permitida somente
ao final da instrução. Essa restrição aplica-se apenas ao especificar UNION, EXCEPT e INTERSECT em uma
consulta de nível superior e não em uma subconsulta. Consulte a seção de Exemplos a seguir.

A cláusula ORDER BY é inválida em exibições, funções embutidas, tabelas derivadas e subconsultas, a


menos que as cláusulas TOP ou OFFSET e FETCH também estejam especificadas.Quando ORDER BY é usada
nesses objetos, a cláusula é utilizada apenas para determinar as linhas retornadas pela cláusula TOP ou
pelas cláusulas OFFSET e FETCH. A cláusula ORDER BY não garante resultados ordenados quando essas
construções são consultadas, a menos que ORDER BY também seja especificada na própria consulta.

Não há suporte para OFFSET e FETCH exibições indexadas ou em uma exibição definida usando a
cláusula de CHECK OPTION.

OFFSET e FETCH podem ser usadas em qualquer consulta que permita TOP e ORDER BY, com as
seguintes limitações:

 A cláusula OVER não dá suporte a OFFSET e FETCH.


 Não é possível especificar OFFSET e FETCH diretamente em instruções INSERT, UPDATE, MERGE e
DELETE, mas elas podem ser especificadas em uma subconsulta definida nessas instruções. Por
exemplo, na instrução INSERT INTO SELECT, OFFSET e FETCH podem ser especificadas na instrução
SELECT.
 Em uma consulta que use operadores UNION, EXCEPT ou INTERSECT, OFFSET e FETCH podem ser
especificadas somente na consulta final que define a ordem dos resultados da consulta.
 Não é possível combinar TOP com OFFSET e FETCH na mesma expressão de consulta (no mesmo
escopo de consulta).

Usando OFFSET e FETCH para limitar as linhas retornadas

18
É recomendável usar as cláusulas OFFSET e FETCH em vez da cláusula TOP para implementar uma
solução de paginação de consulta e limitar o número de linhas enviadas a um aplicativo cliente.

O uso de OFFSET e FETCH como solução de paginação exige a execução da consulta uma vez para cada
"página" de dados retornados para o aplicativo cliente. Por exemplo, para retornar os resultados de uma
consulta em incrementos de 10 linhas, você deve executar a consulta uma vez para retornar as linhas 1 a 10,
depois executar a consulta novamente para retornar as linhas 11 a 20 e assim por diante. Cada consulta é
independente e elas não são relacionadas entre si. Isso significa que, diferentemente de usar um cursor no
qual a consulta é executada uma vez e o estado é mantido no servidor, o aplicativo cliente é responsável
para controlar o estado. Para obter resultados estáveis entre solicitações de consulta que usam OFFSET e
FETCH, as seguintes condições devem ser atendidas:

1. Os dados subjacentes que são usados pela consulta não devem ser alterados. Ou seja, as linhas
afetadas pela consulta não são atualizadas ou todas as solicitações de páginas da consulta são
executadas em uma única transação usando isolamento de transação serializável ou de
instantâneo.
2. A cláusula ORDER BY contém uma coluna ou combinação de colunas cuja exclusividade é
garantida.

Consulte o exemplo "Executando várias consultas em uma única transação" na seção de Exemplos
posteriormente neste tópico.

Se planos de execução consistentes forem importantes na sua solução de paginação, considere o uso
da dica de consulta OPTIMIZE FOR para os parâmetros OFFSET e FETCH. Consulte "Especificado expressões
para valores de OFFSET e FETCH" na seção de Exemplos posteriormente neste tópico.

Exemplos

CATEGORIA ELEMENTOS DE SINTAXE EM DESTAQUE


Sintaxe básica ORDER BY
Especificando a ordem crescente e decrescente DESC • ASC
Especificando uma ordenação COLLATE
Especificando uma ordem condicional expressão CASE
Usando ORDER BY em uma função de classificação Funções de classificação
Limitando o número de linhas retornadas OFFSET • FETCH
Usando ORDER BY com UNION, EXCEPT e INTERSECT UNION

Sintaxe básica

Os exemplos nesta seção demonstram a funcionalidade básica da cláusula ORDER BY usando a sintaxe
mínima necessária.

A. Especificando uma única coluna definida na lista de seleção

O exemplo a seguir classifica o conjunto de resultados pela coluna numérica ProductID. Como não foi
especificada nenhuma ordem de classificação específica, o padrão (ordem crescente) é usado.

SQL
USE AdventureWorks2012;
GO
SELECT ProductID, Name FROM Production.Product
WHERE Name LIKE 'Lock Washer%'

19
ORDER BY ProductID;

B. Especificando uma única coluna não definida na lista de seleção

O exemplo a seguir classifica o conjunto de resultados por uma coluna que não está incluída na lista de
seleção, mas que foi definida na tabela especificada na cláusula FROM.

SQL
USE AdventureWorks2012;
GO
SELECT ProductID, Name, Color
FROM Production.Product
ORDER BY ListPrice;

C. Especificando um alias como a coluna de classificação

O exemplo a seguir especifica o alias de coluna SchemaName como a coluna da ordem de classificação.

SQL
USE AdventureWorks2012;
GO
SELECT name, SCHEMA_NAME(schema_id) AS SchemaName
FROM sys.objects
WHERE type = 'U'
ORDER BY SchemaName;

D. Especificando uma expressão como a coluna de classificação

O exemplo a seguir usa uma expressão como a coluna de classificação. A expressão é definida usando a
função DATEPART para classificar o conjunto de resultados pelo ano no qual os funcionários foram
contratados.

SQL
USE AdventureWorks2012;
GO
SELECT BusinessEntityID, JobTitle, HireDate
FROM HumanResources.Employee
ORDER BY DATEPART(year, HireDate);

Especificando a ordem de classificação crescente e decrescente

A. Especificando uma ordem decrescente

O exemplo a seguir classifica o conjunto de resultados pela coluna numérica ProductID na ordem
decrescente.

SQL
USE AdventureWorks2012;
GO
SELECT ProductID, Name FROM Production.Product
WHERE Name LIKE 'Lock Washer%'
20
ORDER BY ProductID DESC;

B. Especificando uma ordem crescente

O exemplo a seguir classifica o conjunto de resultados pela coluna Name na ordem crescente. Os
caracteres são classificados em ordem alfabética e não em ordem numérica. Ou seja, 10 é tem uma
classificação anterior a 2.

SQL
USE AdventureWorks2012;
GO
SELECT ProductID, Name FROM Production.Product
WHERE Name LIKE 'Lock Washer%'
ORDER BY Name ASC ;

C. Especificando as ordens crescente e decrescente

O exemplo a seguir classifica o conjunto de resultados por duas colunas. O conjunto de resultados da
consulta é classificado primeiro na ordem crescente pela coluna FirstName e, em seguida, na ordem
decrescente pela coluna LastName.

SQL
USE AdventureWorks2012;
GO
SELECT LastName, FirstName FROM Person.Person
WHERE LastName LIKE 'R%'
ORDER BY FirstName ASC, LastName DESC ;

Especificando uma ordenação

O exemplo a seguir mostra como a especificação de uma ordenação na cláusula ORDER BY pode alterar
a ordem na qual os resultados da consulta são retornados. É criada uma tabela que contém uma coluna
definida usando uma ordenação sem diferenciação de maiúsculas e minúsculas, nem de acentos. Os valores
são inseridos com várias diferenças de maiúsculas e minúsculas e de acentos. Como não foi especificado
uma ordenação na cláusula ORDER BY, a primeira consulta usa a ordenação da coluna ao classificar os
valores. Na segunda consulta, uma ordenação com diferenciação de maiúsculas e minúsculas e de assentos
é especificada na cláusula ORDER BY, o que altera a ordem na qual as linhas são retornadas.

SQL
USE tempdb;
GO
CREATE TABLE #t1 (name nvarchar(15) COLLATE Latin1_General_CI_AI)
GO
INSERT INTO #t1 VALUES(N'Sánchez'),(N'Sanchez'),(N'sánchez'),(N'sanchez');

-- This query uses the collation specified for the column 'name' for sorting.
SELECT name
FROM #t1
ORDER BY name;
-- This query uses the collation specified in the ORDER BY clause for
sorting.

21
SELECT name
FROM #t1
ORDER BY name COLLATE Latin1_General_CS_AS;

Especificando uma ordem condicional

O exemplo a seguir usa a expressão CASE em uma cláusula ORDER BY para determinar
condicionalmente a ordem de classificação das linhas com base em um determinado valor de coluna. No
primeiro exemplo, é avaliado o valor da coluna SalariedFlag da
tabela HumanResources.Employee. Funcionários que têm o SalariedFlag definido como 1 são retornados
pelo BusinessEntityID em ordem decrescente. Funcionários que têm o SalariedFlag definido como 0 são
retornados pelo BusinessEntityID em ordem crescente. No segundo exemplo, o conjunto de resultados será
ordenado pela coluna TerritoryName quando a coluna CountryRegionName for igual a 'United States' e
por CountryRegionName para todas as outras linhas.

SQL
SELECT BusinessEntityID, SalariedFlag
FROM HumanResources.Employee
ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC
,CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END;
GO

SQL
SELECT BusinessEntityID, LastName, TerritoryName, CountryRegionName
FROM Sales.vSalesPerson
WHERE TerritoryName IS NOT NULL
ORDER BY CASE CountryRegionName WHEN 'United States' THEN TerritoryName
ELSE CountryRegionName END;

Usando ORDER BY em uma função de classificação

O exemplo as seguir usa a cláusula ORDER BY nas funções de classificação ROW_NUMBER, RANK,
DENSE_RANK e NTILE.

SQL
USE AdventureWorks2012;
GO
SELECT p.FirstName, p.LastName
,ROW_NUMBER() OVER (ORDER BY a.PostalCode) AS "Row Number"
,RANK() OVER (ORDER BY a.PostalCode) AS "Rank"
,DENSE_RANK() OVER (ORDER BY a.PostalCode) AS "Dense Rank"
,NTILE(4) OVER (ORDER BY a.PostalCode) AS "Quartile"
,s.SalesYTD, a.PostalCode
FROM Sales.SalesPerson AS s
INNER JOIN Person.Person AS p
ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address AS a
ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL AND SalesYTD <> 0;

22
Limitando o número de linhas retornadas

Os exemplos as seguir usam OFFSET e FETCH para limitar o número de linhas retornadas por uma consulta.

Aplica-se a: SQL Server 2012 (11.x) a SQL Server 2017 e Banco de dados SQL do Azure.

A. Especificando constantes inteiras para valores de OFFSET e FETCH

O exemplo a seguir especifica uma constante inteira como o valor das cláusulas OFFSET e FETCH.A
primeira consulta retorna todas as linhas classificadas pela coluna DepartmentID. Compare os resultados
retornados por essa consulta com os resultados das duas consultas seguintes. A próxima consulta usa a
cláusula OFFSET 5 ROWS para ignorar as cinco primeiras linhas e retornar todas as linhas restantes. A
consulta final usa a cláusula OFFSET 0 ROWS para iniciar com a primeira linha e depois usa FETCH NEXT 10
ROWS ONLY para limitar as linhas retornadas a 10 linhas do conjunto de resultados classificado.

SQL
USE AdventureWorks2012;
GO
-- Return all rows sorted by the column DepartmentID.
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID;

-- Skip the first 5 rows from the sorted result set and return all remaining
rows.
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID OFFSET 5 ROWS;

-- Skip 0 rows and return only the first 10 rows from the sorted result set.
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY;

B. Especificando variáveis para valores de OFFSET e FETCH

O exemplo a seguir declara as variáveis @StartingRowNumber e @FetchRows, e especifica essas variáveis


nas cláusulas OFFSET e FETCH.

SQL
USE AdventureWorks2012;
GO
-- Specifying variables for OFFSET and FETCH values
DECLARE @StartingRowNumber tinyint = 1
, @FetchRows tinyint = 8;
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC
OFFSET @StartingRowNumber ROWS
FETCH NEXT @FetchRows ROWS ONLY;

23
C. Especificando expressões para valores de OFFSET e FETCH

O exemplo a seguir usa a expressão @StartingRowNumber - 1 para especificar o valor de OFFSET e a


expressão @EndingRowNumber - @StartingRowNumber + 1 para especificar o valor de FETCH. Além disso, é
especificada a dica de consulta, OPTIMIZE FOR. Essa dica pode ser usada para fornecer um valor específico
para uma variável local quando a consulta é compilada e otimizada. O valor é usado somente durante a
otimização da consulta e não durante sua execução.

SQL
USE AdventureWorks2012;
GO

-- Specifying expressions for OFFSET and FETCH values


DECLARE @StartingRowNumber tinyint = 1
, @EndingRowNumber tinyint = 8;
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC
OFFSET @StartingRowNumber - 1 ROWS
FETCH NEXT @EndingRowNumber - @StartingRowNumber + 1 ROWS ONLY
OPTION ( OPTIMIZE FOR (@StartingRowNumber = 1, @EndingRowNumber = 20) );

D. Especificando uma subconsulta escalar de constante para valores de OFFSET e FETCH

O exemplo a seguir usa uma subconsulta escalar de constante para definir o valor para a cláusula FETCH. A
subconsulta retorna um único valor da coluna PageSize da tabela dbo.AppSettings.

SQL
-- Specifying a constant scalar subquery
USE AdventureWorks2012;
GO
CREATE TABLE dbo.AppSettings (AppSettingID int NOT NULL, PageSize int NOT
NULL);
GO
INSERT INTO dbo.AppSettings VALUES(1, 10);
GO
DECLARE @StartingRowNumber tinyint = 1;
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC
OFFSET @StartingRowNumber ROWS
FETCH NEXT (SELECT PageSize FROM dbo.AppSettings WHERE AppSettingID = 1)
ROWS ONLY;

E. Executando várias consultas em uma única transação

O exemplo a seguir mostra um método de implementação de uma solução de paginação que assegura que
sejam retornados resultados estáveis em todas as solicitações da consulta. A consulta é executada em uma
única transação usando o nível de isolamento do instantâneo e a coluna especificada na cláusula ORDER BY
assegura a exclusividade da coluna.

24
SQL
USE AdventureWorks2012;
GO

-- Ensure the database can support the snapshot isolation level set for the query.
IF (SELECT snapshot_isolation_state FROM sys.databases WHERE name =
N'AdventureWorks2012') = 0
ALTER DATABASE AdventureWorks2012 SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

-- Set the transaction isolation level to SNAPSHOT for this query.


SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
GO

-- Beging the transaction


BEGIN TRANSACTION;
GO
-- Declare and set the variables for the OFFSET and FETCH values.
DECLARE @StartingRowNumber int = 1
, @RowCountPerPage int = 3;

-- Create the condition to stop the transaction after all rows have been returned.
WHILE (SELECT COUNT(*) FROM HumanResources.Department) >= @StartingRowNumber
BEGIN

-- Run the query until the stop condition is met.


SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC
OFFSET @StartingRowNumber - 1 ROWS
FETCH NEXT @RowCountPerPage ROWS ONLY;

-- Increment @StartingRowNumber value.


SET @StartingRowNumber = @StartingRowNumber + @RowCountPerPage;
CONTINUE
END;
GO
COMMIT TRANSACTION;
GO

Usando ORDER BY com UNION, EXCEPT e INTERSECT

Quando uma consulta usa os operadores UNION, EXCEPT ou INTERSECT, a cláusula ORDER BY deve ser
especificada no final da instrução e os resultados das consultas combinadas são classificados. O exemplo as
seguir retorna todos os produtos que são vermelhos ou amarelos e classifica essa lista combinada pela
coluna ListPrice.

SQL
USE AdventureWorks2012;
GO
SELECT Name, Color, ListPrice
FROM Production.Product
WHERE Color = 'Red'
-- ORDER BY cannot be specified here.
UNION ALL
SELECT Name, Color, ListPrice
FROM Production.Product
WHERE Color = 'Yellow'
ORDER BY ListPrice ASC;

25
Cláusula FROM mais JOIN, APPLY, PIVOT

No Transact-SQL, a cláusula FROM está disponível nas seguintes instruções:

 DELETE
 UPDATE
 SELECT

A cláusula FROM geralmente é necessária na instrução SELECT. A exceção é quando nenhuma coluna
de tabela é listada e os únicos itens listados são literais ou variáveis ou expressões aritméticas.

Este artigo também descreve as seguintes palavras-chave que podem ser usadas na cláusula FROM:

 JOIN
 APPLY
 PIVOT

Sintaxe

SQL
-- Syntax for SQL Server and Azure SQL Database

[ FROM { <table_source> } [ ,...n ] ]


<table_source> ::=
{
table_or_view_name [ [ AS ] table_alias ]
[ <tablesample_clause> ]
[ WITH ( < table_hint > [ [ , ]...n ] ) ]
| rowset_function [ [ AS ] table_alias ]
[ ( bulk_column_alias [ ,...n ] ) ]
| user_defined_function [ [ AS ] table_alias ]
| OPENXML <openxml_clause>
| derived_table [ [ AS ] table_alias ] [ ( column_alias [ ,...n ] ) ]
| <joined_table>
| <pivoted_table>
| <unpivoted_table>
| @variable [ [ AS ] table_alias ]
| @variable.function_call ( expression [ ,...n ] )
[ [ AS ] table_alias ] [ (column_alias [ ,...n ] ) ]
| FOR SYSTEM_TIME <system_time>
}
<tablesample_clause> ::=
TABLESAMPLE [SYSTEM] ( sample_number [ PERCENT | ROWS ] )
[ REPEATABLE ( repeat_seed ) ]

<joined_table> ::=
{
<table_source> <join_type> <table_source> ON <search_condition>
| <table_source> CROSS JOIN <table_source>
| left_table_source { CROSS | OUTER } APPLY right_table_source
| [ ( ] <joined_table> [ ) ]
}
<join_type> ::=
26
[ { INNER | { { LEFT | RIGHT | FULL } [ OUTER ] } } [ <join_hint> ] ]
JOIN

<pivoted_table> ::=
table_source PIVOT <pivot_clause> [ [ AS ] table_alias ]

<pivot_clause> ::=
( aggregate_function ( value_column [ [ , ]...n ])
FOR pivot_column
IN ( <column_list> )
)

<unpivoted_table> ::=
table_source UNPIVOT <unpivot_clause> [ [ AS ] table_alias ]

<unpivot_clause> ::=
( value_column FOR pivot_column IN ( <column_list> ) )

<column_list> ::=
column_name [ ,...n ]

<system_time> ::=
{
AS OF <date_time>
| FROM <start_date_time> TO <end_date_time>
| BETWEEN <start_date_time> AND <end_date_time>
| CONTAINED IN (<start_date_time> , <end_date_time>)
| ALL
}

<date_time>::=
<date_time_literal> | @date_time_variable

<start_date_time>::=
<date_time_literal> | @date_time_variable

<end_date_time>::=
<date_time_literal> | @date_time_variable

Argumentos

<table_source>

Especifica uma tabela, exibição, variável de tabela ou origem de tabela derivada, com ou sem um alias,
a ser usada na instrução Transact-SQL. Até 256 origens da tabela podem ser usadas em uma instrução,
embora o limite varie de acordo com a memória disponível e a complexidade de outras expressões na
consulta. Consultas individuais podem não aceitar até 256 origens de tabela.

Observação
O desempenho da consulta pode ser prejudicado com um grande número de tabelas referenciadas em
uma consulta. O tempo de compilação e otimização também é afetado por outros fatores. Esses fatores
incluem a presença de índices e exibições indexadas em cada <table_source> e o tamanho de
<select_list> na instrução SELECT.

27
A ordem de origens de tabela após a palavra-chave FROM não afeta o conjunto de resultados que é
retornado. O SQL Server retorna erros quando aparecem nomes duplicados na cláusula FROM.

table_or_view_name
É o nome de uma tabela ou exibição.

Se a tabela ou exibição existir em outro banco de dados na mesma instância do SQL Server, use um
nome totalmente qualificado no formato database.schema.object_name.

Se a tabela ou exibição existir fora da instância do SQL Server, use um nome de quatro partes no
formato linked_server.catalog.schema.object. Para obter mais informações, consulte sp_addlinkedserver
(Transact-SQL). Um nome de quatro partes que é construído por meio da função OPENDATASOURCE como a
parte do servidor no nome também pode ser usado para especificar a origem da tabela remota. Quando
OPENDATASOURCE é especificado, database_name e schema_name podem não se aplicar a todas as fontes
de dados e podem estar sujeitos às funcionalidades do Provedor OLE DB que acessa o objeto remoto.

[AS] table_alias

É um alias para table_source que pode ser usado por conveniência ou para distinguir uma tabela ou
exibição em uma autojunção ou subconsulta. Em geral, um alias é um nome de tabela abreviado usado para
referência a colunas específicas das tabelas em uma junção. Se o nome da coluna existir em mais de uma
tabela na junção, o SQL Server exigirá que ele seja qualificado por um nome de tabela, nome de exibição ou
alias. O nome da tabela não poderá ser usado se um alias estiver definido.

Quando uma tabela derivada, um conjunto de linhas, uma função com valor de tabela ou uma cláusula
de operador (como PIVOT ou UNPIVOT) é usado, o table_alias obrigatório no final da cláusula é o nome da
tabela associado para todas as colunas retornadas, incluindo colunas de agrupamento.

WITH (<table_hint> )

Especifica que o otimizador de consulta use uma estratégia de otimização ou bloqueio com esta tabela
e para esta instrução. Para obter mais informações, consulte Dicas de tabela (Transact-SQL).

rowset_function

Aplica-se a: SQL Server 2008 a SQL Server 2017 e Banco de Dados SQL.

Especifica uma das funções de conjunto de linhas, como OPENROWSET, que retorna um objeto que
pode ser usado no lugar de uma referência de tabela. Para obter mais informações sobre uma lista de
funções de conjunto de linhas, consulte Funções de conjunto de linhas (Transact-SQL).

O uso das funções OPENROWSET e OPENQUERY para especificar que um objeto remoto depende dos
recursos do provedor OLE DB que acessa o objeto.

bulk_column_alias

Aplica-se a: SQL Server 2008 a SQL Server 2017 e Banco de Dados SQL.

É um alias opcional para substituir um nome de coluna no conjunto de resultados. Os aliases de coluna
são permitidos somente em instruções SELECT que usam a função OPENROWSET com a opção BULK. Ao
usar bulk_column_alias, especifique um alias para cada coluna da tabela na mesma ordem que as colunas
no arquivo.

Observação
28
Este alias substitui o atributo NAME nos elementos COLUMN de um arquivo de formato XML, se houver.

user_defined_function
Especifica uma função com valor de tabela.

OPENXML <openxml_clause>

Aplica-se a: SQL Server 2008 a SQL Server 2017 e Banco de Dados SQL.

Fornece uma exibição de conjunto de linhas em um documento XML. Para obter mais informações,
consulte OPENXML (SQL Server).

derived_table

É uma subconsulta que recupera linhas do banco de dados. derived_table é usada como entrada para a
consulta externa.

derived _table pode usar o recurso do construtor de valor de tabela Transact-SQL para especificar
várias linhas. Por exemplo, SELECT * FROM (VALUES (1, 2), (3, 4), (5, 6), (7, 8), (9, 10) ) AS MyTable(a,
b);. Para obter mais informações, consulte Construtor de valor de tabela (Transact-SQL).

column_alias

É um alias opcional para substituir um nome de coluna no conjunto de resultados da tabela


derivada. Inclua um alias para cada coluna na lista de seleção e encerre a lista completa de aliases de coluna
entre parênteses.

table_or_view_name FOR SYSTEM_TIME <system_time>

Aplica-se a: SQL Server 2016 (13.x) a SQL Server 2017 e Banco de Dados SQL.

Especifica que uma versão específica dos dados é retornada da tabela temporal especificada e sua
tabela de histórico vinculada com controle de versão do sistema

Cláusula Tablesample

Aplica-se a: SQL Server, Banco de Dados SQL

Especifica que uma amostra de dados da tabela é retornada. A amostra pode ser aproximada.Esta
cláusula pode ser usada em qualquer tabela primária ou unida em uma instrução SELECT ou
UPDATE. TABLESAMPLE não pode ser especificado com exibições.

Observação
Quando você usa TABLESAMPLE em bancos de dados atualizados para o SQL Server, o nível de
compatibilidade do banco de dados é definido como 110 ou mais alto, PIVOT não é permitido em uma
consulta CTE (expressão de tabela comum) recursiva. Para obter mais informações, veja Nível de
compatibilidade de ALTER DATABASE (Transact-SQL).

SYSTEM

É um método de amostragem dependente de implementação especificado por padrões ISO. No SQL


Server, esse é o único método de amostragem disponível e é aplicado por padrão. SYSTEM aplica um

29
método de amostragem baseado em páginas em que um conjunto aleatório de páginas de uma tabela é
escolhido para a amostra, e todas as linhas dessas páginas são retornadas como subconjunto da amostra.

sample_number

É uma expressão numérica constante exata ou aproximada que representa o percentual ou o número
de linhas. Quando especificado com PERCENT, sample_number é convertido implicitamente em um
valor float; caso contrário, é convertido em bigint. PERCENT é o padrão.

PERCENT

Especifica que um percentual sample_number das linhas da tabela deve ser recuperado da
tabela.Quando PERCENT é especificado, o SQL Server retorna um valor aproximado do percentual
especificado. Quando PERCENT é especificado, a expressão sample_number deve ser avaliada como um
valor de 0 a 100.

ROWS

Especifica que, aproximadamente, sample_number de linhas será recuperado. Quando ROWS é


especificado, o SQL Server retorna uma aproximação do número de linhas especificado. Quando ROWS é
especificado, a expressão sample_number deve ser avaliada como um valor inteiro maior que zero.

REPEATABLE

Indica que a amostra selecionada pode ser retornada novamente. Quando for especificado com o
mesmo valor de repeat_seed, o SQL Server retornará o mesmo subconjunto de linhas, desde que não seja
feita nenhuma alteração nas linhas da tabela. Quando for especificado com outro valor de repeat_seed,
o SQL Server provavelmente retornará uma amostra diferente das linhas da tabela. As seguintes ações na
tabela são consideradas alterações: inserir, atualizar, excluir, recompilação do índice ou desfragmentação e
restauração ou anexação do banco de dados.

repeat_seed

É uma expressão de inteiro constante usada pelo SQL Server para gerar um número
aleatório.repeat_seed é bigint. Se repeat_seed não for especificado, SQL Server atribuirá um valor
aleatório.Para um valor repeat_seed específico, o resultado da amostragem será sempre o mesmo se
nenhuma alteração tiver sido aplicada à tabela. A expressão repeat_seed deve ser avaliada como um inteiro
maior que zero.

Cláusula Tablesample

Aplica-se a: SQL Data Warehouse

Especifica que uma amostra de dados da tabela é retornada. A amostra pode ser aproximada.Esta
cláusula pode ser usada em qualquer tabela primária ou unida em uma instrução SELECT ou
UPDATE. TABLESAMPLE não pode ser especificado com exibições.

PERCENT

Especifica que um percentual sample_number das linhas da tabela deve ser recuperado da
tabela.Quando PERCENT é especificado, o SQL Data Warehouse retorna um valor aproximado do percentual

30
especificado. Quando PERCENT é especificado, a expressão sample_number precisa ser avaliada como um
valor de 0 a 100.

Tabela unida

Uma tabela unida é um conjunto de resultados que é o produto de duas ou mais tabelas. Para várias
junções, use parênteses para alterar a ordem natural das junções.

Tipo de junção

Especifica o tipo de operação de junção.

INNER = Especifica todos os pares de linhas correspondentes retornados. Descarta as linhas não
correspondentes de ambas as tabelas. Quando nenhum tipo de junção é especificado, este é o padrão.

FULL [ OUTER ] = Especifica que uma linha da tabela esquerda ou direita que não atende à condição de
junção seja incluída no conjunto de resultados, e as colunas de saída correspondentes à outra tabela sejam
definidas como NULL. Isso ocorre além de todas as linhas normalmente retornadas por INNER JOIN.

LEFT [ OUTER ] = Especifica que todas as linhas da tabela esquerda que não atendem à condição de
junção sejam incluídas no conjunto de resultados, e as colunas de saída da outra tabela sejam definidas
como NULL além de todas as linhas retornadas pela junção interna.

RIGHT [OUTER] = Especifica que todas as linhas da tabela direita que não atendem à condição de
junção sejam incluídas no conjunto de resultados, e as colunas de saída que correspondem à outra tabela
sejam definidas como NULL, além de todas as linhas retornadas pela junção interna.

Dica de junção

Para o SQL Server e Banco de Dados SQL, especifica que o otimizador de consulta do SQL Serverusa
uma dica de junção, ou um algoritmo de execução, por junção especificada na cláusula FROM da
consulta. Para obter mais informações, consulte Dicas de junção (Transact-SQL).

Para o SQL Data Warehouse e Parallel Data Warehouse, essas dicas de junção se aplicam a junções
INNER em duas colunas incompatíveis com a distribuição. Elas podem melhorar o desempenho da consulta
restringindo a quantidade de movimentação de dados que ocorre durante o processamento da consulta. As
dicas de junção permitidas para o SQL Data Warehousee Parallel Data Warehouse são as seguintes:

REDUCE = Reduz o número de linhas a serem movidas para a tabela no lado direito da junção, a fim de
tornar compatíveis as duas tabelas incompatíveis com a distribuição. A dica REDUCE também é chamada de
uma dica de semijunção.

REPLICATE = Faz com que os valores na coluna de junção da tabela no lado esquerdo da junção sejam
replicados para todos os nós. A tabela à direita é unida à versão replicada dessas colunas.

REDISTRIBUTE = Força duas fontes de dados a serem distribuídas nas colunas especificadas na cláusula
JOIN. Para uma tabela distribuída, o Parallel Data Warehouse executará uma movimentação de ordem
aleatória. Para uma tabela replicada, o Parallel Data Warehouse executará uma movimentação de
corte. Para entender esses tipos de movimentação, consulte a seção "Operações de plano de consulta DMS"
no tópico "Noções básicas sobre planos de consulta" no Documentação de produto do Parallel Data
Warehouse. Essa dica pode melhorar o desempenho quando o plano de consulta usa uma movimentação de
difusão para resolver uma junção incompatível com a distribuição.

31
JOIN = Indica que a operação de junção especificada deve acontecer entre as origens de tabela ou
exibições especificadas.

ON <search_condition> = Especifica o critério no qual a junção se baseia. Os critérios podem


especificar qualquer predicado, embora colunas e operadores de comparação sejam frequentemente
usados, por exemplo:

SQL
SELECT p.ProductID, v.BusinessEntityID
FROM Production.Product AS p
JOIN Purchasing.ProductVendor AS v
ON (p.ProductID = v.ProductID);
Quando o critério especifica colunas, estas não precisam ter o mesmo nome ou o mesmo tipo de
dados; no entanto, se os tipos de dados não forem iguais, eles deverão ser compatíveis ou tipos que o SQL
Server possa converter implicitamente. Se os tipos de dados não puderem ser convertidos implicitamente, o
critério deverá converter o tipo de dados explicitamente usando a função CONVERT.

Poderá haver predicados que envolvam somente uma das tabelas unidas na cláusula ON. Tais
predicados também podem estar na cláusula WHERE da consulta. Embora a presença de tais predicados não
faça diferença para junções INNER, eles podem gerar um resultado diferente quando junções OUTER estão
envolvidas. Isso ocorre porque os predicados na cláusula ON são aplicados à tabela antes da junção, ao
passo que a cláusula WHERE é semanticamente aplicada ao resultado da junção.

Para obter mais informações sobre critérios de pesquisa e predicados, consulte Critério de pesquisa
(Transact-SQL).

CROSS JOIN = Especifica o produto cruzado de duas tabelas. Retorna as mesmas linhas como se
nenhuma cláusula WHERE estivesse especificada em uma junção em estilo antigo que não seja SQL-92.

left_table_source { CROSS | OUTER } APPLY right_table_source


Especifica que a right_table_source do operador APPLY é avaliada em cada linha da left_table_source. Essa
funcionalidade é útil quando a right_table_source contém uma função com valor de tabela que usa valores
de coluna da left_table_source como um de seus argumentos.

É necessário especificar CROSS ou OUTER com APPLY. Quando CROSS é especificado, nenhuma linha é
produzida quando a right_table_source é avaliada em uma linha especificada da left_table_source e retorna
um conjunto de resultados vazio.

Quando OUTER é especificado, uma linha é produzida para cada linha da left_table_source, mesmo
quando a right_table_source é avaliada nessa linha e retorna um conjunto de resultados vazio.

left_table_source

É uma origem de tabela conforme a definição no argumento anterior. Para obter mais informações,
consulte a seção Comentários.

right_table_source

É uma origem de tabela conforme a definição no argumento anterior. Para obter mais informações,
consulte a seção Comentários.

Cláusula PIVOT

32
table_source PIVOT <pivot_clause>

Especifica que a table_source é dinamizada com base na pivot_column. table_source é uma tabela ou
uma expressão de tabela. A saída é uma tabela que contém todas as colunas da table_source, exceto
a pivot_column e value_column. As colunas da table_source, exceto a pivot_column e a value_column, são
chamadas as colunas de agrupamento do operador original. Para obter mais informações sobre PIVOT e
UNPIVOT, consulte Usando PIVOT e UNPIVOT.

PIVOT executa uma operação de agrupamento na tabela de entrada em relação às colunas de


agrupamento e retorna uma linha para cada grupo. Além disso, a saída contém uma coluna para cada valor
especificado na column_list exibido na pivot_column da input_table.

Para obter mais informações, consulte a seção Comentários a seguir.

aggregate_function

É um sistema ou uma função de agregação definida pelo usuário que aceita uma ou mais entradas. A
função de agregação deve ser invariável para valores nulos. Uma função de agregação invariável para
valores nulos não considera valores nulos no grupo enquanto está avaliando o valor de agregação.

A função de agregação de sistema COUNT (*) não é permitida.

value_column

É a coluna de valor do operador PIVOT. Quando usado com UNPIVOT, value_column não pode ser o
nome de uma coluna existente na table_source de entrada.

FOR pivot_column

É a coluna dinâmica do operador PIVOT. pivot_column deve ser de um tipo implícita ou explicitamente
conversível em nvarchar() . Esta coluna não pode ser image ou rowversion.

Quando UNPIVOT é usado, pivot_column é o nome da coluna de saída que é reduzida com base
na table_source. Não pode haver uma coluna em table_source com esse nome.

IN (column_list )

Na cláusula PIVOT, lista os valores na pivot_column que se tornarão os nomes de coluna da tabela de
saída. A lista não pode especificar nomes de coluna já existentes na table_source de entrada que está sendo
dinamizada.

Na cláusula UNPIVOT, lista as colunas na table_source que serão reduzidas a uma única pivot_column.

table_alias

É o nome do alias da tabela de saída. pivot_table_alias deve ser especificado.

UNPIVOT <unpivot_clause>

Especifica que a tabela de entrada é reduzida com base em várias colunas na column_list a uma única
coluna chamada pivot_column. Para obter mais informações sobre PIVOT e UNPIVOT, consulte Usando
PIVOT e UNPIVOT.

AS OF <date_time>

33
Aplica-se a: SQL Server 2016 (13.x) a SQL Server 2017 e Banco de Dados SQL.

Retorna uma tabela com um único registro para cada linha que contém os valores que foram reais
(atuais) no momento passado especificado. Internamente, uma união é executada entre a tabela temporal e
sua tabela de histórico e os resultados são filtrados para retornar os valores na linha que era válida no ponto
no tempo especificado pelo parâmetro <date_time> . O valor de uma linha é considerado válido se o valor
de system_start_time_column_name é menor ou igual ao valor do parâmetro <date_time> e o valor
de system_end_time_column_name é maior que o valor do parâmetro <date_time> .

FROM <start_date_time> TO <end_date_time>

Aplica-se a: SQL Server 2016 (13.x) a SQL Server 2017 e Banco de Dados SQL.

Retorna uma tabela com os valores para todas as versões de registro que estavam ativas no intervalo
de tempo especificado, sem levar em conta se eles começaram a estar ativos antes do valor de
parâmetro <start_date_time> para o argumento FROM ou deixaram de estar ativos após o valor de
parâmetro <end_date_time> para o argumento TO. Internamente, uma união é executada entre a tabela
temporal e sua tabela de histórico e os resultados são filtrados para retornar os valores para todas as
versões de linha que estavam ativas a qualquer momento durante o intervalo de tempo especificado. As
linhas que se tornaram ativas exatamente no limite inferior definido pelo ponto de extremidade FROM são
incluídas e as linhas que se tornaram ativas exatamente no limite superior definido pelo ponto de
extremidade TO não são incluídas.

BETWEEN <start_date_time> AND <end_date_time>

Aplica-se a: SQL Server 2016 (13.x) a SQL Server 2017 e Banco de Dados SQL.

A mesma descrição acima para FROM <start_date_time> TO <end_date_time> é válida, exceto que
ela inclui linhas que se tornaram ativas no limite superior definido pelo ponto de extremidade
<end_date_time>.

CONTAINED IN (<start_date_time>, <end_date_time>)

Aplica-se a: SQL Server 2016 (13.x) a SQL Server 2017 e Banco de Dados SQL.

Retorna uma tabela com os valores para todas as versões de registro que foram abertas e fechadas
dentro do intervalo de tempo especificado definido por dois valores de data e hora para o argumento
CONTAINED IN. As linhas que se tornaram ativas exatamente no limite inferior ou que deixaram de ser
ativas exatamente no limite superior são incluídas.

ALL

Retorna uma tabela com os valores de todas as linhas da tabela atual e da tabela de histórico.

Remarks

A cláusula FROM aceita a sintaxe SQL-92 para tabelas unidas e derivadas. Sintaxe SQL-92 fornece os
operadores de junção INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER e CROSS.

Há suporte para UNION e JOIN em uma cláusula FROM dentro de exibições e em tabelas derivadas e
subconsultas.

34
Uma autojunção é uma tabela unida a ela mesma. As operações de inserção ou atualização que são
baseadas em uma autojunção seguem a ordem da cláusula FROM.

Como o SQL Server considera as estatísticas de distribuição e cardinalidade de servidores vinculados


que fornecem estatísticas de distribuição de coluna, a dica de junção REMOTE não é necessária para impor a
avaliação de uma junção remotamente. O processador de consulta do SQL Server considera estatísticas
remotas e determina se uma estratégia da junção remota é apropriada. A dica de junção REMOTE é útil para
provedores que não fornecem estatísticas de distribuição de coluna.

Usando APPLY

Ambos os operandos à esquerda e à direita do operador APPLY são expressões de tabela. A principal
diferença entre esses operandos é que right_table_source pode usar uma função com valor de tabela que
usa uma coluna da left_table_source como um dos argumentos da função. A left_table_source pode incluir
funções com valor de tabela, mas não pode conter argumentos que são colunas da right_table_source.

O operador APPLY funciona da seguinte maneira para criar a origem de tabela para a cláusula FROM:

1. Avalia right_table_source em cada linha da left_table_source para produzir conjuntos de linhas.

Os valores na right_table_source dependem de left_table_source. right_table_source pode ser


representada aproximadamente da seguinte maneira: TVF(left_table_source.row), em que TVF é uma
função com valor de tabela.

2. Combina os conjuntos de resultados que são produzidos para cada linha na avaliação de
right_table_source com a left_table_source executando uma operação UNION ALL.

A lista de colunas produzida pelo resultado do operador APPLY é o conjunto de colunas da


left_table_source combinado à lista de colunas da right_table_source.

Usando PIVOT e UNPIVOT

A pivot_column e a value_column são colunas de agrupamento usadas pelo operador PIVOT. Este
segue o seguinte processo para obter o conjunto de resultados de saída:

1. Executa um GROUP BY em sua input_table nas colunas de agrupamento e produz uma linha de
saída para cada grupo.

As colunas de agrupamento na linha de saída obtêm os valores de coluna correspondentes para o


grupo na input_table.

2. Gera valores para as colunas da lista de colunas para cada linha de saída da seguinte forma:

a. Agrupando ainda as linhas geradas em GROUP BY na etapa anterior na pivot_column.

Para cada coluna de saída na column_list, selecionando um subgrupo que atenda à


condição:

pivot_column = CONVERT(<data type of pivot_column>, 'output_column')

b. aggregate_function é avaliada na value_column desse subgrupo e seu resultado é retornado


como o valor da output_column correspondente. Se o subgrupo estiver vazio, o SQL

35
Server gerará um valor nulo para essa output_column. Se a função de agregação for COUNT
e o subgrupo estiver vazio, será retornado zero (0).

Observação
Os identificadores de coluna na cláusula UNPIVOT seguem a ordenação de catálogo. Para o Banco de
Dados SQL, a ordenação é sempre SQL_Latin1_General_CP1_CI_AS. Para bancos de dados parcialmente
independentes do SQL Server, a ordenação é sempre Latin1_General_100_CI_AS_KS_WS_SC. Se a coluna
for combinada com outras colunas, uma cláusula COLLATE (COLLATE DATABASE_DEFAULT) será
necessária para evitar conflitos.

Permissões

Requer as permissões para a instrução DELETE, SELECT ou UPDATE.

Exemplos

A. Usando uma cláusula FROM simples

O exemplo a seguir recupera as colunas TerritoryID e Name da tabela SalesTerritory no banco de dados de
exemplo AdventureWorks2012.

SQL
SELECT TerritoryID, Name
FROM Sales.SalesTerritory
ORDER BY TerritoryID ;

Aqui está o conjunto de resultados.

SQL
TerritoryID Name
----------- ------------------------------
1 Northwest
2 Northeast
3 Central
4 Southwest
5 Southeast
6 Canada
7 France
8 Germany
9 Australia
10 United Kingdom
(10 row(s) affected)

Usando as dicas de otimizador TABLOCK e HOLDLOCK

A transação parcial a seguir mostra como posicionar um bloqueio de tabela compartilhado explícito
em Employee e como ler o índice. O bloqueio é mantido ao longo de toda a transação.

SQL
BEGIN TRAN
SELECT COUNT(*)
FROM HumanResources.Employee WITH (TABLOCK, HOLDLOCK) ;

36
C. Usando a sintaxe SQL-92 CROSS JOIN

O exemplo a seguir retorna o produto cruzado das tabelas Employee e Department no banco de
dados AdventureWorks2012. Uma lista de todas as possíveis combinações de linhas de BusinessEntityID e
todas as linhas de nome de Department é retornada.

SQL
SELECT e.BusinessEntityID, d.Name AS Department
FROM HumanResources.Employee AS e
CROSS JOIN HumanResources.Department AS d
ORDER BY e.BusinessEntityID, d.Name ;

D. Usando a sintaxe SQL-92 FULL OUTER JOIN

O exemplo a seguir retorna o nome do produto e quaisquer ordens de venda correspondentes na


tabela SalesOrderDetail no banco de dados AdventureWorks2012. Ele também retorna as ordens de venda
que não têm produtos listados na tabela Product, bem como produtos com uma ordem de venda diferente
daquela listada na tabela Product.

SQL
-- The OUTER keyword following the FULL keyword is optional.
SELECT p.Name, sod.SalesOrderID
FROM Production.Product AS p
FULL OUTER JOIN Sales.SalesOrderDetail AS sod
ON p.ProductID = sod.ProductID
ORDER BY p.Name ;

E. Usando a sintaxe SQL-92 LEFT OUTER JOIN

O exemplo a seguir une duas tabelas em ProductID e preserva as linhas não correspondentes da tabela
esquerda. É feita a correspondência da tabela Product com a tabela SalesOrderDetail nas
colunas ProductID em cada tabela. Todos os produtos, ordenados ou não, aparecem no conjunto de
resultados.

SQL
SELECT p.Name, sod.SalesOrderID
FROM Production.Product AS p
LEFT OUTER JOIN Sales.SalesOrderDetail AS sod
ON p.ProductID = sod.ProductID
ORDER BY p.Name ;

F. Usando a sintaxe SQL-92 INNER JOIN

O exemplo a seguir retorna todos os nomes de produtos e IDs de ordens de venda.

SQL
-- By default, SQL Server performs an INNER JOIN if only the JOIN
-- keyword is specified.
SELECT p.Name, sod.SalesOrderID
FROM Production.Product AS p

37
INNER JOIN Sales.SalesOrderDetail AS sod
ON p.ProductID = sod.ProductID
ORDER BY p.Name ;

G. Usando a sintaxe SQL-92 RIGHT OUTER JOIN

O exemplo a seguir une duas tabelas em TerritoryID e preserva as linhas não correspondentes da tabela
direita. É feita a correspondência da tabela SalesTerritory com a tabela SalesPersonna coluna TerritoryID em
cada tabela. Todos os vendedores aparecem no conjunto de resultados, tenham ou não um território
atribuído.

SQL
SELECT st.Name AS Territory, sp.BusinessEntityID
FROM Sales.SalesTerritory AS st
RIGHT OUTER JOIN Sales.SalesPerson AS sp
ON st.TerritoryID = sp.TerritoryID ;
H. Usando dicas de junção HASH e MERGE

O exemplo a seguir executa uma junção de três tabelas entre as


tabelas Product, ProductVendore Vendor para criar uma lista de produtos e seus fornecedores. O
otimizador de consulta une Product e ProductVendor (p e pv) usando uma junção MERGE. Em seguida, os
resultados da junção MERGE de Product e ProductVendor (p e pv) são unidos por HASH à
tabela Vendor para criar (p e pv) e v.

Importante
Após uma dica de junção ser especificada, a palavra-chave INNER não é mais opcional e deve ser
explicitamente declarada para a execução de uma INNER JOIN.

SQL
SELECT p.Name AS ProductName, v.Name AS VendorName
FROM Production.Product AS p
INNER MERGE JOIN Purchasing.ProductVendor AS pv
ON p.ProductID = pv.ProductID
INNER HASH JOIN Purchasing.Vendor AS v
ON pv.BusinessEntityID = v.BusinessEntityID
ORDER BY p.Name, v.Name ;

I. Usando uma tabela derivada

O exemplo a seguir usa uma tabela derivada, uma instrução SELECT após a clausula FROM, para retornar o
nome e o sobrenome de todos os funcionários e as cidades em que moram.

SQL
SELECT RTRIM(p.FirstName) + ' ' + LTRIM(p.LastName) AS Name, d.City
FROM Person.Person AS p
INNER JOIN HumanResources.Employee e ON p.BusinessEntityID = e.BusinessEntityID
INNER JOIN
(SELECT bea.BusinessEntityID, a.City
FROM Person.Address AS a
INNER JOIN Person.BusinessEntityAddress AS bea
ON a.AddressID = bea.AddressID) AS d
ON p.BusinessEntityID = d.BusinessEntityID
ORDER BY p.LastName, p.FirstName;

38
J. Usando TABLESAMPLE para ler dados de uma amostra de linhas em uma tabela

O exemplo a seguir usa TABLESAMPLE na cláusula FROM para retornar aproximadamente 10 por cento de
todas as linhas na tabela Customer.

SQL
SELECT *
FROM Sales.Customer TABLESAMPLE SYSTEM (10 PERCENT) ;

K. Usando APPLY

O seguinte exemplo presume que as seguintes tabelas e função com valor de tabela estejam presentes no
banco de dados:

Object Name Nomes de coluna


Departamentos DeptID, DivisionID, DeptName, DeptMgrID
EmpMgr MgrID, EmpID
funcionários EmpID, EmpLastName, EmpFirstName, EmpSalary
GetReports(MgrID) EmpID, EmpLastName, EmpSalary

A função com valor de tabela GetReports retorna a lista de todos os funcionários que se reportam direta ou
indiretamente ao MgrID especificado. O exemplo usa APPLY para retornar todos os departamentos e todos
os funcionários do departamento. Se um departamento em particular não tiver funcionários, não haverá
linhas retornadas para ele.

SQL
SELECT DeptID, DeptName, DeptMgrID, EmpID, EmpLastName, EmpSalary
FROM Departments d
CROSS APPLY dbo.GetReports(d.DeptMgrID) ;
Se desejar que a consulta gere linhas para os departamentos sem funcionários, o que irá gerar valores nulos
para as colunas EmpID, EmpLastName e EmpSalary, use então OUTER APPLY.

SQL
SELECT DeptID, DeptName, DeptMgrID, EmpID, EmpLastName, EmpSalary
FROM Departments d
OUTER APPLY dbo.GetReports(d.DeptMgrID) ;

L. Usando CROSS APPLY

O exemplo a seguir recupera um instantâneo de todos os planos de consulta residindo no cache de plano,
consultando a exibição de gerenciamento dinâmico sys.dm_exec_cached_plans para recuperar os
identificadores de plano de todas as consultas no cache. Em seguida, o operador CROSS APPLY é
especificado para transmitir o identificador de plano a sys.dm_exec_query_plan. A saída de plano de
execução XML de cada plano atualmente no cache de plano está na coluna query_plan da tabela retornada.

SQL
USE master;
GO
SELECT dbid, object_id, query_plan
FROM sys.dm_exec_cached_plans AS cp

39
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle);
GO

M. Usando FOR SYSTEM_TIME

O exemplo a seguir usa o argumento FOR SYSTEM_TIME AS OF date_time_literal_or_variable para retornar


linhas da tabela que eram reais (atuais) a partir de 1º de janeiro de 2014.

SQL
SELECT DepartmentNumber,
DepartmentName,
ManagerID,
ParentDepartmentNumber
FROM DEPARTMENT
FOR SYSTEM_TIME AS OF '2014-01-01'
WHERE ManagerID = 5;

O exemplo a seguir usa o argumento FOR SYSTEM_TIME FROM date_time_literal_or_variable TO


date_time_literal_or_variable para retornar todas as linhas que estavam ativas durante o período definido
começando em 1º de janeiro de 2013 e terminando em 1º de janeiro de 2014, excluindo o limite superior.

SQL
SELECT DepartmentNumber,
DepartmentName,
ManagerID,
ParentDepartmentNumber
FROM DEPARTMENT
FOR SYSTEM_TIME FROM '2013-01-01' TO '2014-01-01'
WHERE ManagerID = 5;

O exemplo a seguir usa o argumento FOR SYSTEM_TIME BETWEEN date_time_literal_or_variable AND


date_time_literal_or_variable para retornar todas as linhas que estavam ativas durante o período definido
começando em 1º de janeiro de 2013 e terminando em 1º de janeiro de 2014, incluindo o limite superior.

SQL
SELECT DepartmentNumber,
DepartmentName,
ManagerID,
ParentDepartmentNumber
FROM DEPARTMENT
FOR SYSTEM_TIME BETWEEN '2013-01-01' AND '2014-01-01'
WHERE ManagerID = 5;

O exemplo a seguir usa o argumento FOR SYSTEM_TIME CONTAINED IN (date_time_literal_or_variable,


date_time_literal_or_variable) para retornar todas as linhas que estavam abertas e fechadas durante o
período definido começando em 1º de janeiro de 2013 e terminando em 1º de janeiro de 2014.

SQL
SELECT DepartmentNumber,
DepartmentName,
ManagerID,
ParentDepartmentNumber
FROM DEPARTMENT
FOR SYSTEM_TIME CONTAINED IN ( '2013-01-01', '2014-01-01' )

40
WHERE ManagerID = 5;

O exemplo a seguir usa uma variável em vez de um literal para fornecer os valores de limite de data para a
consulta.

SQL
DECLARE @AsOfFrom datetime2 = dateadd(month,-12, sysutcdatetime());
DECLARE @AsOfTo datetime2 = dateadd(month,-6, sysutcdatetime());

SELECT DepartmentNumber,
DepartmentName,
ManagerID,
ParentDepartmentNumber
FROM DEPARTMENT
FOR SYSTEM_TIME FROM @AsOfFrom TO @AsOfTo
WHERE ManagerID = 5;

41