SELECT ROW_NUMBER () tem garantia de retornar resultados classificados pelos números de linha gerados?

10

Por exemplo, considere a consulta SQL:

SELECT
   A.[Name],
   ROW_NUMBER() OVER(ORDER BY A.[Name] ASC)
FROM
   [FooTable] AS A

Aqui, observo os resultados retornados, classificados por A. [Nome]. Se eu alterar a coluna de classificação definida na função ROW_NUMBER para outra coluna, novamente os resultados serão classificados por essa coluna.

Eu esperava que o número da linha fosse atribuído às linhas, mas não esperava que as linhas retornassem classificadas pelo mesmo critério. Isso é simplesmente um efeito colateral de como a consulta está sendo executada (no meu caso no SQL Server 2008 R2) ou esse comportamento é garantido? (Não encontrei referência a essa garantia).

redcalx
fonte
10
Nunca há qualquer garantia. Sempre. A menos que você diga ao SQL Server como solicitar algo, é livre retornar os dados na ordem que desejar. Ao deixar de fora o pedido, você está dizendo ao SQL Server que não se importa com o pedido. Se você deseja uma garantia, basta digitar a cláusula ORDER BY.
Aaron Bertrand
Há uma boa razão para perguntar, pois a cláusula de ordenação em questão é muito complexa e, portanto, a cópia cria um lastro de manutenção de código e aumenta a probabilidade de defeitos futuros. A outra alternativa é uma refatoração menor que pensei poder evitar se o padrão SQL definisse uma ordem de classificação implícita. De qualquer forma, eu estava interessado apenas se havia documentação formal cobrindo esse ponto.
Redcalx #
11
então por que não fazer essa pergunta?
Aaron Bertrand

Respostas:

14

Se você fez a pergunta, acho que realmente queria perguntar:

Como posso pedir ROW_NUMBER()sem repetir a ORDER BYexpressão complexa ?

Poderíamos ter dito para você criar um alias para a ROW_NUMBER()expressão e classificar usando o alias:

SELECT
   A.[Name],
   rn = ROW_NUMBER() OVER (ORDER BY <complex expression>)
FROM
   dbo.[FooTable] AS A
ORDER BY rn;

Agora você só precisa alterar a expressão em um local e a classificação resultante será baseada nessa expressão sem precisar repeti-la.

Aaron Bertrand
fonte
6
De fato, repeating the complex ORDER BY expressionnem garante que a saída será emitida por ordem ROW_NUMBER (). A menos que as colunas na cláusula ORDER BY formem uma chave exclusiva.
孔夫子
22

Absolutamente não. Prova:

SELECT
   A.[Name],
   ROW_NUMBER() OVER(ORDER BY A.[Name] ASC),
   ROW_NUMBER() OVER(ORDER BY A.[Name] DESC)
FROM
   [FooTable] AS A

A única maneira de garantir um pedido no SQL é solicitar, usar ORDER BYno próprio resultado.

Remus Rusanu
fonte
OK, adicionarei mais uma qualificação - os resultados são garantidos para serem classificados se apenas uma cláusula ROW_NUMBER () for especificada.
Redbull #
22
A única maneira de garantir uma ordem no SQL é perguntar para ele
Remus Rusanu
0

Na verdade, a questão (antiga) poderia ser estendida para incluir também a partição por parte, pois parece haver uma ordem implícita primeiro pela partição e depois pela ordem por parte (s)

Portanto, não é tão simples como alguns sugeriram para atribuir o número da linha e usá-lo para fazer pedidos.

Também precisaríamos de um sql aninhado para extrair a partição por cláusula (se não quisermos simplesmente repeti-la, é claro)

Empiricamente , parecemos ter a última linha de pedidos implicitamente

Select
  <field-list>, 
  rn=Row_Number() over(partition by <PartionClause>) order by <OrderClause>
from ....
Order by <PartionClause> asc, rn asc

Mas o que nos falta é qualquer prova ou garantia de que ele sempre seja válido.

(Se houver várias chamadas Row_Number () em execução, é a ÚLTIMA que parece dar a ordem)

OBSERVAÇÃO TAMBÉM: se você adicionar explicitamente a ordem pelo plano de execução, mostrará claramente uma etapa final de classificação, e classificar um conjunto já classificado é o pior dos casos; portanto, leva muito mais tempo com o Order By do que sem

Eske Rahn
fonte
11
Isso realmente não responde à pergunta e parece discordar da resposta aceita e de uma resposta altamente votada.
Erik Darling
Concordo que o meu é mais um comentário do que uma resposta. Bem, a resposta aceita não é realmente uma resposta, exceto que diz que é melhor não confiarmos na ordem - e era essa a pergunta. Pode ser visto pelo plano de execução que ele realmente faz uma classificação e, se adicionarmos uma ordem explícita, obteremos uma segunda classificação. Mas isso não é uma prova, é apenas parte do conhecimento empírico
Eske Rahn
(É claro que ele só faz o tipo se não houver um índice adequado que pode ser usado para acessar a tabela, mas apenas acrescentou que para mostrar que não é geralmente para dar explicitamente a ordem de custo-livre)
Eske Rahn