La première suggestion de Pradeep Adiga ORDER BY NEWID()
, est très bien et quelque chose que j'ai utilisé dans le passé pour cette raison.
Soyez prudent avec l'utilisation RAND()
- dans de nombreux contextes, elle n'est exécutée qu'une fois par instruction, elle ORDER BY RAND()
n'aura donc aucun effet (car vous obtenez le même résultat de RAND () pour chaque ligne).
Par exemple:
SELECT display_name, RAND() FROM tr_person
renvoie chaque nom de notre table person et un nombre "aléatoire", qui est le même pour chaque ligne. Le nombre varie chaque fois que vous exécutez la requête, mais il est le même pour chaque ligne à chaque fois.
Pour montrer que c'est la même chose avec RAND()
utilisé dans une ORDER BY
clause, j'essaye:
SELECT display_name FROM tr_person ORDER BY RAND(), display_name
Les résultats sont toujours classés par nom, ce qui indique que le champ de tri précédent (celui qui devrait être aléatoire) n'a aucun effet et a donc probablement toujours la même valeur.
La commande par NEWID()
fonctionne cependant, car si NEWID () n'était pas toujours réévalué, le but des UUID serait rompu lors de l'insertion de nombreuses nouvelles lignes dans un même statut avec des identifiants uniques lors de leur clé, donc:
SELECT display_name FROM tr_person ORDER BY NEWID()
ne commande les noms « au hasard ».
Autres SGBD
Ce qui précède est vrai pour MSSQL (2005 et 2008 au moins, et si je me souviens bien 2000 également). Une fonction renvoyant un nouvel UUID doit être évaluée à chaque fois dans tous les SGBD NEWID () est sous MSSQL mais cela vaut la peine de le vérifier dans la documentation et / ou par vos propres tests. Le comportement d'autres fonctions de résultats arbitraires, comme RAND (), est plus susceptible de varier entre les SGBD, alors vérifiez à nouveau la documentation.
J'ai également vu que l'ordre des valeurs UUID était ignoré dans certains contextes, car la base de données suppose que le type n'a pas d'ordre significatif. Si vous trouvez que c'est le cas, convertissez explicitement l'UUID en un type de chaîne dans la clause de commande, ou encapsulez une autre fonction autour de celle-ci comme CHECKSUM()
dans SQL Server (il peut y avoir une petite différence de performances par rapport à cela car la commande sera effectuée sur une valeur 32 bits et non une valeur 128 bits, bien que si l'avantage de cela l'emporte sur le coût de fonctionnement CHECKSUM()
par valeur, je vous laisse tester).
Note latérale
Si vous voulez un ordre arbitraire mais quelque peu répétable, triez par un sous-ensemble relativement incontrôlé des données dans les lignes elles-mêmes. Par exemple, l'un ou l'autre retournera les noms dans un ordre arbitraire mais répétable:
SELECT display_name FROM tr_person ORDER BY CHECKSUM(display_name), display_name -- order by the checksum of some of the row's data
SELECT display_name FROM tr_person ORDER BY SUBSTRING(display_name, LEN(display_name)/2, 128) -- order by part of the name field, but not in any an obviously recognisable order)
Les commandes arbitraires mais répétables ne sont pas souvent utiles dans les applications, mais peuvent être utiles pour tester si vous voulez tester du code sur les résultats dans une variété d'ordres mais que vous voulez pouvoir répéter chaque exécution de la même manière plusieurs fois (pour obtenir un timing moyen résultats sur plusieurs exécutions, ou tester qu'un correctif que vous avez apporté au code supprime un problème ou une inefficacité précédemment mis en évidence par un jeu de résultats d'entrée particulier, ou simplement pour tester que votre code est "stable", c'est-à-dire qu'il renvoie le même résultat à chaque fois si envoyé les mêmes données dans un ordre donné).
Cette astuce peut également être utilisée pour obtenir des résultats plus arbitraires à partir de fonctions, qui n'autorisent pas les appels non déterministes comme NEWID () dans leur corps. Encore une fois, ce n'est pas quelque chose qui est susceptible d'être souvent utile dans le monde réel, mais qui pourrait être utile si vous voulez qu'une fonction renvoie quelque chose de aléatoire et "random-ish" est assez bon (mais attention à vous rappeler les règles qui déterminent lorsque les fonctions définies par l'utilisateur sont évaluées, c'est-à-dire généralement une seule fois par ligne, ou vos résultats peuvent ne pas être ceux que vous attendez / exigez).
Performance
Comme le souligne EBarr, il peut y avoir des problèmes de performance avec l'un des éléments ci-dessus. Pour plus de quelques lignes, vous êtes presque assuré de voir la sortie mise en file d'attente vers tempdb avant la lecture du nombre de lignes demandé dans le bon ordre, ce qui signifie que même si vous recherchez le top 10, vous pouvez trouver un index complet l'analyse (ou pire, l'analyse de table) se produit avec un énorme bloc d'écriture dans tempdb. C'est pourquoi il peut être d'une importance vitale, comme pour la plupart des choses, de comparer des données réalistes avant de les utiliser en production.