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.
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…