¿Existe una forma sucinta de recuperar un registro aleatorio de una tabla de servidor SQL?
Me gustaría aleatorizar mis datos de prueba unitaria, así que estoy buscando una forma sencilla de seleccionar una identificación aleatoria de una tabla. En inglés, la selección sería "Seleccione una identificación de la tabla donde la identificación es un número aleatorio entre la identificación más baja en la tabla y la identificación más alta en la tabla".
No puedo encontrar una manera de hacerlo sin tener que ejecutar la consulta, probar un valor nulo y luego volver a ejecutar si es nulo.
Ideas?
sql-server
tsql
random
Jeremy
fuente
fuente
Respuestas:
si
SELECT TOP 1 * FROM table ORDER BY NEWID()
Explicación
Se
NEWID()
genera A para cada fila y luego la tabla se ordena por ella. Se devuelve el primer registro (es decir, el registro con el GUID "más bajo").Notas
Los GUID se generan como números pseudoaleatorios desde la versión cuatro:
- Un espacio de nombres URN de identificador universalmente único (UUID) - RFC 4122
La alternativa
SELECT TOP 1 * FROM table ORDER BY RAND()
no funcionará como uno pensaría.RAND()
devuelve un solo valor por consulta, por lo que todas las filas compartirán el mismo valor.Si bien los valores de GUID son pseudoaleatorios, necesitará un PRNG mejor para las aplicaciones más exigentes.
El rendimiento típico es de menos de 10 segundos para alrededor de 1.000.000 de filas, por supuesto, dependiendo del sistema. Tenga en cuenta que es imposible alcanzar un índice, por lo que el rendimiento será relativamente limitado.
fuente
En tablas más grandes, también puede usar
TABLESAMPLE
esto para evitar escanear toda la tabla.SELECT TOP 1 * FROM YourTable TABLESAMPLE (1000 ROWS) ORDER BY NEWID()
El
ORDER BY NEWID
sigue siendo necesaria para evitar filas que acaban de volver que aparecen por primera vez en la página de datos.El número que se utilizará debe elegirse cuidadosamente para el tamaño y la definición de la tabla y puede considerar la lógica de reintento si no se devuelve ninguna fila. Las matemáticas detrás de esto y por qué la técnica no es adecuada para tablas pequeñas se discuten aquí.
fuente
TOP 1
que no importa si las filas en la misma página están correlacionadas o no. Solo estás eligiendo uno de ellos.También pruebe su método para obtener una identificación aleatoria entre MIN (Id) y MAX (Id) y luego
SELECT TOP 1 * FROM table WHERE Id >= @yourrandomid
Siempre te dará una fila.
fuente
Si desea seleccionar datos grandes, la mejor manera que conozco es:
SELECT * FROM Table1 WHERE (ABS(CAST( (BINARY_CHECKSUM (keycol1, NEWID())) as int)) % 100) < 10
Fuente: MSDN
fuente
Estaba buscando mejorar los métodos que había probado y encontré esta publicación. Me doy cuenta de que es antiguo, pero este método no figura en la lista. Estoy creando y aplicando datos de prueba; esto muestra el método para "dirección" en un SP llamado con @st (estado de dos caracteres)
Create Table ##TmpAddress (id Int Identity(1,1), street VarChar(50), city VarChar(50), st VarChar(2), zip VarChar(5)) Insert Into ##TmpAddress(street, city, st, zip) Select street, city, st, zip From tbl_Address (NOLOCK) Where st = @st -- unseeded RAND() will return the same number when called in rapid succession so -- here, I seed it with a guaranteed different number each time. @@ROWCOUNT is the count from the most recent table operation. Set @csr = Ceiling(RAND(convert(varbinary, newid())) * @@ROWCOUNT) Select street, city, st, Right(('00000' + ltrim(zip)),5) As zip From ##tmpAddress (NOLOCK) Where id = @csr
fuente
SELECT * FROM Sales.SalesOrderDetail WHERE 0.01 >= CAST(CHECKSUM(NEWID(), SalesOrderID) & 0x7fffffff AS float) / CAST (0x7fffffff AS int)
Esto se explica con más detalle a continuación:
fuente