Aprimorando o resultado da consulta com TOP WITH TIES no SQL Server 2012

Fala galera, existe um recurso útil no SQL Server 2012 que lhe ajuda a aprimorar o retorno da consulta baseado em uma faixa/grupo de registros, ficando mais próximo à sua necessidade. Este recurso é o TOP (__) WITH TIES, e ele funciona obrigatoriamente em conjunto com a clausula ORDER BY, sem essa clausula não conseguimos aplicar esses “filtros” ao resultado.

A clausula TOP eu acredito que todos já saibam como utilizar. A novidade é o TOP WITH TIES, que informa ao resultset a incluir também o valor idêntico ao do ultimo registro encontrado, com base na coluna que tenha sido especificada na clausula do ORDER BY.

Para exemplificar, veja o código abaixo com o TOP convencional, retornando as 5 linhas:

SELECT TOP (5) SalesOrderID, ModifiedDate, ProductID
FROM Sales.SalesOrderDetail
ORDER BY ModifiedDate DESC;

SalesOrderID ModifiedDate ProductID
75084 2008-07-31 00:00:00.000 876
75085 2008-07-31 00:00:00.000 712
75085 2008-07-31 00:00:00.000 877
75086 2008-07-31 00:00:00.000 877
75087 2008-07-31 00:00:00.000 707

 

Já o código abaixo repete todos os registros encontrados que são idênticos à ultima linha do TOP (5) da coluna ModifiedDate, resultando em 96 registros ao invés de apenas 5. Este resultado se dá ao fato do comando WITH TIES retornar todos os valores da coluna informada no ORDER BY, entendendo que o valor faz parte da amostra de dados que você gostaria de retornar. O valor da coluna ModifiedDate do ultimo registro é 2008-07-31 00:00:00.000 então todas as ocorrências com esse mesmo valor serão adicionadas ao resultado da busca.

SELECT TOP (5) WITH TIES SalesOrderID, ModifiedDate, ProductID
FROM Sales.SalesOrderDetail
ORDER BY ModifiedDate DESC;
SalesOrderID ModifiedDate ProductID
75084 2008-07-31 00:00:00.000 876
75085 2008-07-31 00:00:00.000 712
75085 2008-07-31 00:00:00.000 877
… (outros 90 registros)
75123 2008-07-31 00:00:00.000 878
75123 2008-07-31 00:00:00.000 879
75123 2008-07-31 00:00:00.000 712

 

Se o código acima tivesse sido escrito com a coluna ProductId ao invés de ModifiedDate na clausula ORDER BY, o resultado seria de 696 registros e não 96. Isso acontece pois o ProductID encontrado na ultima linha do ORDER BY é o valor 999, então ele adiciona todos os outros registros cujo valor de ProductID também seja 999.


Pra fazer uma analogia com uma paixão nacional, veja abaixo a tabela referente à 8ª rodada do Campeonato Brasileiro 2012.

image

Executando o código com o TOP (4) convencional, o resultado chegaria até o Botafogo.

SELECT TOP(4) Time, PG
FROM Brasileirao2012
ORDER BY PG DESC

Time PG
Atlético-MG 19
Fluminense 18
Vasco 17
Botafogo 15

Adicionando a clausula WITH TIES, os times que tem a mesma pontuação do Botafogo são incluidos ao resultado. Sendo assim, o resultset adiciona o São Paulo e o Internacional, mas o Cruzeiro fica de fora porque sua pontuação não é a mesma que a do Botafogo.

SELECT TOP(4) WITH TIES Time, PG
FROM Brasileirao2012
ORDER BY PG DESC
Time PG
Atlético-MG 19
Fluminense 18
Vasco 17
Botafogo 15
São Paulo 15
Internacional 15

Caso você inclua mais de uma coluna na clausula ORDER BY, ele segue o mesmo comportamento, adicionando os registros iguais ao valor encontrado na ultima linha do resultset, porém, baseado em mais de uma coluna.

Veja o código abaixo, com o resultado de duas colunas na clausula ORDER BY.


SELECT TOP (5) SalesOrderID, ModifiedDate, ProductID
FROM Sales.SalesOrderDetail
ORDER BY ModifiedDate, ProductID DESC;
SalesOrderID ModifiedDate ProductID
43659 2005-07-01 00:00:00.000 778
43661 2005-07-01 00:00:00.000 778
43664 2005-07-01 00:00:00.000 778
43665 2005-07-01 00:00:00.000 778
43667 2005-07-01 00:00:00.000 778

 

Reparem que a coluna ModifiedDate tem o valor 2005-07-01 00:00:00.000 e a coluna ProductID tem o valor 778 no ultimo registro do GROUP BY. Já o código com WITH TIES abaixo retorna 9 registros, pois a combinação do valor de ModifiedDate e ProductID se repetem por mais 4 vezes.


SELECT TOP (5) WITH TIES SalesOrderID, ModifiedDate, ProductID
FROM Sales.SalesOrderDetail
ORDER BY ModifiedDate, ProductID DESC;
SalesOrderID ModifiedDate ProductID
43659 2005-07-01 00:00:00.000 778
43661 2005-07-01 00:00:00.000 778
43664 2005-07-01 00:00:00.000 778
43665 2005-07-01 00:00:00.000 778
43667 2005-07-01 00:00:00.000 778
43676 2005-07-01 00:00:00.000 778
43683 2005-07-01 00:00:00.000 778
43693 2005-07-01 00:00:00.000 778
43695 2005-07-01 00:00:00.000 778

 

Geralmente utilizamos o TOP para uma amostragem de valores quando não são necessários todos os registros. Incluir o WITH TIES melhora nossa “massa de dados” de retorno, adicionando TODOS os valores que você solicitou na ordenação…

Sobre Diego Nogare 344 Artigos
Diego Nogare é Gerente Técnico de Engenharia de Machine Learning no Itaú-Unibanco. Também é professor em programas de pós graduação no Mackenzie e na FIAP, em São Paulo. Foi nomeado como Microsoft MVP por 11 anos seguidos, e hoje faz parte do programa Microsoft Regional Director.