Seleccione N loggings aleatorios en SQL Server sin repetición

¿Cómo selecciono N loggings aleatorios de una tabla a la vez sin repetición de loggings devueltos previamente por la misma operación?

Una solución obvia es:

SELECT TOP 5 * FROM MyTable WHERE Id NOT IN (SELECT Id FROM PreviouslyReturned) ORDER BY newid() 

Pero, ¿no sería realmente ineficiente a medida que MyTable comienza a crecer?

Tengo una larga list de loggings y requiero cinco loggings a la vez para un juego basado en turnos sin repetir ninguno de los loggings ya obtenidos para el juego dado. Como sé aproximadamente cuántos giros tendrá lugar, podría seleccionar una muestra aleatoria antes de que comience el juego que sea significativamente grande, pero preferiría que fuera "dynamic". Encontré esta pregunta , que usa una semilla aleatoria con MySQL.

Eventualmente habrá tantos loggings que la repetición no será un problema (loggings >> N), pero hasta entonces, necesito que los loggings sean únicos. En una nota al margen, uso Fluent NHibernate para mi capa de persistencia; quizás NHibernate tenga alguna característica que lo permita.

sin repetir ninguno de los loggings

Eso no se llama seleccionar loggings aleatorios entre los progtwigdores. Los valores seleccionados random se repiten más a menudo de lo que piensas, y de hecho contar el número y la duración de las repeticiones es una manera en que los estadísticos detectan el engaño.

Lo que estás buscando se llama " shuffle" . Mezclar aleatoriza el order de un set finito de cosas, como cartas o llaves. (Aleatorizar el order de las filas no significa lo mismo que seleccionar filas random).

En su caso, planifique almacenar el set de keys ya utilizado para cada usuario. Seleccione un set aleatorio de filas que aún no están en ese set. Hay varias forms de almacenar cada set aleatorio de filas (keys); asegúrese de poder decir cuál es el último o actual set.

Simplemente podría almacenar todas las keys principales de su tabla en una segunda tabla, seleccionarlas random de esta (recuperando las filas asociadas de la tabla original) y eliminarlas después de la selección (desde la tabla auxiliar, por supuesto).

Esperaría que esta forma fuera más eficiente que almacenar las keys ya utilizadas y build una cláusula WHERE NOR IN (resp. EXCEPT ) (eliminar debería ser aproximadamente tan eficaz como insert, y seleccionar debería funcionar significativamente más rápido sin una cláusula adicional). Pero, por supuesto, esto debería probarse (mediante el perfil …)

Seleccionar cinco identificadores aleatorios debería funcionar bien usando el enfoque en la pregunta que ha citado.

Tratar

 SELECT TOP 5 * FROM YOUR_TABLE ORDER BY CHECKSUM(NEWID()) 

Hay una pregunta relacionada que entra en detalles sobre la semántica de la selección aleatoria aleatoria aquí: Selección aleatoria no siempre está devolviendo una sola fila

SQL Server evalúa RAND una vez por consulta, lo que significa que el truco mySQL no funcionará de todos modos.

Editar: esto también es adecuado

 SELECT TOP 5 * FROM YOUR_TABLE ORDER BY NEWID() 

Leí tu pregunta actualizada y tengo otra sugerencia:
Crear una vista indexada en

 SELECT mt.* FROM MyTable mt LEFT JOIN PreviouslyReturned pr ON mt.Id = pr.Id WHERE pr.Id Is NULL 

o algo similar

Entonces

 SELECT TOP 5 * FROM YOUR_INDEXED_VIEW ORDER BY NEWID()