SELECT ROW_NUMBER () garantit-il de renvoyer les résultats triés par les numéros de ligne générés?

10

Par exemple, considérez la requête SQL:

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

Ici, j'observe les résultats renvoyés triés par A. [Nom]. Si je change la colonne de tri définie dans la fonction ROW_NUMBER en une autre colonne, les résultats sont de nouveau triés par cette colonne.

Je m'attendais à ce que le numéro de ligne soit attribué aux lignes, mais je ne m'attendais pas à ce que les lignes reviennent triées selon les mêmes critères. Est-ce simplement un effet secondaire de la façon dont la requête est exécutée (dans mon cas sur SQL Server 2008 R2) ou ce comportement est-il garanti? (Je n'ai trouvé aucune référence à une telle garantie).

redcalx
la source
10
Il n'y a jamais de garantie. Déjà. Sauf si vous dites à SQL Server comment commander quelque chose, il est libre de renvoyer les données dans l'ordre qu'il souhaite. En omettant la commande par, vous dites à SQL Server que vous ne vous souciez pas de la commande. Si vous voulez une garantie, tapez déjà la clause ORDER BY.
Aaron Bertrand
Il y a une bonne raison de demander car la clause de commande en question est très complexe et donc la copie crée à la fois un ballast de maintenance du code et augmente la probabilité de défauts futurs. L'autre alternative est une refactorisation mineure que je pensais pouvoir éviter si le standard SQL définissait un ordre de tri implicite. En tout cas, je voulais simplement savoir s'il existait une documentation officielle couvrant ce point.
redcalx
1
alors pourquoi ne pas poser cette question?
Aaron Bertrand

Réponses:

14

Si vous aviez posé la question, je pense que vous vouliez réellement vous poser:

Comment puis-je commander ROW_NUMBER()sans répéter l' ORDER BYexpression complexe ?

Nous aurions pu vous dire de créer un alias pour l' ROW_NUMBER()expression, puis de trier à l'aide de l'alias:

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

Il ne vous reste plus qu'à modifier l'expression au même endroit et le tri résultant sera basé sur cette expression sans avoir à la répéter.

Aaron Bertrand
la source
6
En fait, repeating the complex ORDER BY expressioncela ne garantit même pas que la sortie sortira par la commande ROW_NUMBER (). À moins que les colonnes de la clause ORDER BY ne forment une clé unique.
22

Absolument pas. Preuve:

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

La seule façon de garantir une commande en SQL est de la demander, d'utiliser ORDER BYsur le résultat lui-même.

Remus Rusanu
la source
OK, j'ajouterai une autre qualification - les résultats sont-ils garantis pour être triés si une seule clause ROW_NUMBER () est spécifiée.
redcalx
22
La seule façon de garantir une commande en SQL est de la demander
Remus Rusanu
0

En fait, la (vieille) question pourrait être étendue pour inclure également la partition par partie, car il semble y avoir un ordre implicite d'abord la partition par , puis l' ordre par partie (s)

Il n'est donc pas aussi simple que certains l'ont suggéré d'assigner le numéro de ligne et de l'utiliser pour la commande.

Nous aurions également besoin d'un sql imbriqué extrayant la clause partition by (si nous ne voulons pas simplement la répéter bien sûr)

Empiriquement, nous semblons obtenir implicitement la dernière ligne de commande

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

Mais ce qui nous manque, c'est une preuve ou une garantie qu'il tient toujours.

(S'il y a plusieurs appels Row_Number () en jeu, c'est le DERNIER qui semble donner l'ordre)

NOTEZ AUSSI si vous ajoutez explicitement l' ordre par le plan d'exécution montre clairement une étape de tri finale, et le tri d'un ensemble déjà trié est en quelque sorte le pire des cas, donc cela prend beaucoup plus de temps avec l' ordre par que sans

Eske Rahn
la source
1
Cela ne répond pas vraiment à la question, et il semble être en désaccord à la fois avec la réponse acceptée et avec une réponse très appréciée.
Erik Darling
Je suis d'accord que le mien est plus un commentaire qu'une réponse. Eh bien, la réponse acceptée n'est pas vraiment une réponse, sauf qu'elle dit que nous ferions mieux de ne pas faire confiance à l'ordre - et c'était la question. Le plan d'exécution peut voir qu'il effectue réellement un tri, et si nous ajoutons un ordre explicite par, nous obtenons un deuxième tri. Mais ce n'est PAS une preuve, ce n'est qu'une partie des connaissances empiriques
Eske Rahn
(Bien sûr, il ne fait le tri que s'il n'y a pas d'index approprié qu'il peut utiliser pour accéder à la table, mais l'ajoute uniquement pour montrer qu'il n'est généralement pas gratuit de donner explicitement la commande)
Eske Rahn