La primera sugerencia de Pradeep Adiga, ORDER BY NEWID()
, está bien y es algo que he utilizado en el pasado por esta razón.
Tenga cuidado con el uso de RAND()
– en muchos contextos sólo se ejecuta una vez por sentencia por lo que ORDER BY RAND()
no tendrá ningún efecto (ya que está obteniendo el mismo resultado de RAND() para cada fila).
Por ejemplo:
SELECT display_name, RAND() FROM tr_person
devuelve cada nombre de nuestra tabla de personas y un número «aleatorio», que es el mismo para cada fila. El número varía cada vez que se ejecuta la consulta, pero es el mismo para cada fila cada vez.
Para mostrar que lo mismo ocurre con RAND()
usado en una cláusula ORDER BY
, pruebo:
SELECT display_name FROM tr_person ORDER BY RAND(), display_name
Los resultados siguen ordenados por el nombre indicando que el campo de ordenación anterior (el que se espera que sea aleatorio) no tiene efecto por lo que presumiblemente siempre tiene el mismo valor.
La ordenación por NEWID()
funciona sin embargo, porque si NEWID() no se reordenara siempre el propósito de los UUIDs se rompería al insertar muchas filas nuevas en un statemnt con identificadores únicos como clave, así que:
SELECT display_name FROM tr_person ORDER BY NEWID()
ordena los nombres «aleatoriamente».
Otros DBMS
Lo anterior es cierto para MSSQL (2005 y 2008 al menos, y si no recuerdo mal 2000 también). Una función que devuelve un nuevo UUID debería ser evaluada cada vez en todos los SGBD NEWID() es bajo MSSQL pero vale la pena verificar esto en la documentación y/o por sus propias pruebas. El comportamiento de otras funciones de resultado arbitrario, como RAND(), es más probable que varíe entre DBMSs, así que de nuevo compruebe la documentación.
También he visto que el ordenamiento por valores UUID es ignorado en algunos contextos ya que la DB asume que el tipo no tiene un ordenamiento significativo. Si usted encuentra que este es el caso explícitamente fundir el UUID a un tipo de cadena en la cláusula de ordenación, o envolver alguna otra función alrededor de ella como CHECKSUM()
en SQL Server (puede haber una pequeña diferencia de rendimiento de este también como el ordenamiento se hará en un valor de 32 bits no uno de 128 bits, aunque si el beneficio de que compensa el costo de ejecutar CHECKSUM()
por valor primero voy a dejar a probar).
Nota al margen
Si quieres una ordenación arbitraria pero algo repetible, ordena por algún subconjunto relativamente incontrolado de los datos en las propias filas. Por ejemplo, cualquiera de estos dos devolverá los nombres en un orden arbitrario pero repetible:
Los ordenamientos arbitrarios pero repetibles no suelen ser útiles en las aplicaciones, aunque pueden ser útiles en las pruebas si quiere probar algún código en los resultados en una variedad de órdenes, pero quiere ser capaz de repetir cada ejecución de la misma manera varias veces (para obtener resultados de tiempo promedio a lo largo de varias ejecuciones, o para probar que una corrección que ha hecho en el código elimina un problema o ineficiencia previamente destacado por un conjunto de resultados de entrada en particular, o simplemente para probar que su código es «estable» en el sentido de que devuelve el mismo resultado cada vez si se envían los mismos datos en un orden determinado).
Este truco también se puede utilizar para obtener resultados más arbitrarios de las funciones, que no permiten llamadas no deterministas como NEWID() dentro de su cuerpo. Una vez más, esto no es algo que probablemente sea útil a menudo en el mundo real, pero podría ser útil si desea que una función devuelva algo al azar y «aleatorio» es lo suficientemente bueno (pero tenga cuidado de recordar las reglas que determinan cuando las funciones definidas por el usuario se evalúan, es decir, por lo general sólo una vez por fila, o sus resultados pueden no ser lo que usted espera / requiere).
Rendimiento
Como EBarr señala, puede haber problemas de rendimiento con cualquiera de los anteriores. Para más de unas pocas filas, está casi garantizado que la salida se enviará a tempdb antes de que el número de filas solicitadas se lea de nuevo en el orden correcto, lo que significa que incluso si usted está buscando el top 10 puede encontrar un escaneo de índice completo (o peor, un escaneo de tabla) junto con un enorme bloque de escritura a tempdb. Por lo tanto, puede ser de vital importancia, como con la mayoría de las cosas, para la evaluación comparativa con los datos realistas antes de usar esto en la producción.