La plupart des bases de données sont assez claires sur le fait qu'un ORDER BY
dans une sous-requête est soit:
- Non autorisé: par exemple, SQL Server, Sybase SQL Anywhere (sauf si complété
TOP
ou OFFSET .. FETCH
)
- Inutile: par exemple PostgreSQL, DB2 (encore une fois, sauf si complété avec
OFFSET .. FETCH
ou LIMIT
)
Voici un exemple tiré du manuel DB2 LUW (c'est moi qui souligne)
Une clause ORDER BY dans une sous-sélection n'affecte pas l'ordre des lignes renvoyées par une requête. Une clause ORDER BY n'affecte l'ordre des lignes renvoyées que si elle est spécifiée dans le fullselect le plus externe.
La formulation est assez explicite, tout comme celle de PostgreSQL :
Si le tri n'est pas choisi, les lignes seront retournées dans un ordre non spécifié. L'ordre réel dans ce cas dépendra des types de plan d'analyse et de jointure et de l'ordre sur le disque, mais il ne faut pas s'y fier . Un ordre de sortie particulier ne peut être garanti que si l'étape de tri est explicitement choisie.
D'après cette spécification, il peut être suivi que tout ordre résultant de la ORDER BY
clause dans une table dérivée est simplement accidentel et peut coïncider par hasard avec votre ordre attendu (ce qu'il fait dans la plupart des bases de données dans votre exemple trivial), mais il serait imprudent de s'appuyer sur cette.
Note latérale sur DB2:
En particulier, DB2 a une fonction moins connue appeléeORDER BY ORDER OF <table-designator>
, qui peut être utilisée comme suit:
SELECT C1 FROM
(SELECT C1 FROM T1
UNION
SELECT C1 FROM T2
ORDER BY C1 ) AS UTABLE
ORDER BY ORDER OF UTABLE
Dans ce cas particulier, l'ordre de la table dérivée peut être explicitement réutilisé dans le plus externe SELECT
Note complémentaire sur Oracle:
Pendant des années, il a été une pratique dans Oracle pour implémenter la OFFSET
pagination à l'aide ROWNUM
, qui ne peut être raisonnablement calculée qu'après avoir commandé une table dérivée:
SELECT *
FROM (
SELECT rownum AS rn, t.* -- ROWNUM here depends on the derived table's ordering
FROM (
SELECT * FROM table ORDER BY time DESC
) t
) t
WHERE rn BETWEEN 10 AND 20
On peut raisonnablement s'attendre à ce qu'au moins en présence d' ROWNUM
une requête, les futures versions d'Oracle ne cassent pas ce comportement afin de ne pas casser à peu près tout l'héritage Oracle SQL, qui n'a pas encore migré vers le plus souhaitable et OFFSET .. FETCH
syntaxe standard lisible de SQL :
SELECT * FROM table ORDER BY time DESC OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY