sql >> Base de Datos >  >> RDS >> Sqlserver

Cómo hacer que RAND() sea determinista en SQL Server

El RAND() La función en SQL Server devuelve un valor flotante pseudoaleatorio de 0 a 1, exclusivo.

Esta función puede ser determinista o no determinista, dependiendo de cómo se invoque.

Las funciones deterministas siempre devuelven el mismo resultado para un conjunto dado de valores de entrada y dado el mismo estado de la base de datos. Las funciones no deterministas pueden devolver un resultado diferente con el mismo conjunto de valores de entrada e incluso si el estado de la base de datos sigue siendo el mismo.

El RAND() La función se puede llamar de dos maneras; con semilla y sin semilla. Si lo llama sin semilla, no es determinista. Si lo llamas con una semilla, es determinista.

En otras palabras, para un valor inicial especificado, el resultado devuelto es siempre el mismo.

Pero hay un problema:a veces llamar a RAND() sin semilla es determinista Lo explico a continuación.

Sintaxis

Primero, aquí está la sintaxis:

RAND ( [ seed ] )

Los corchetes significan que el argumento semilla es opcional.

Ejemplo 1:Sin semilla

Aquí llamo RAND() cinco veces sin semilla.

SELECT RAND() AS [No Seed]
UNION ALL
SELECT RAND()
UNION ALL
SELECT RAND()
UNION ALL
SELECT RAND()
UNION ALL
SELECT RAND()

Resultado:

+-------------------+
| No Seed           |
|-------------------|
| 0.2054995913191   |
| 0.821844434880088 |
| 0.4204955495022   |
| 0.286702661673299 |
| 0.394385747185196 |
+-------------------+

Cada fila tiene un valor diferente.

Ejemplo 2:con semilla

Aquí ejecuto la misma consulta, excepto que agrego la misma semilla a cada llamada de función.

SELECT RAND(100) AS [With Seed]
UNION ALL
SELECT RAND(100)
UNION ALL
SELECT RAND(100)
UNION ALL
SELECT RAND(100)
UNION ALL
SELECT RAND(100)

Resultado:

+-------------------+
| With Seed         |
|-------------------|
| 0.715436657367485 |
| 0.715436657367485 |
| 0.715436657367485 |
| 0.715436657367485 |
| 0.715436657367485 |
+-------------------+

En este caso, todas las filas tienen el mismo valor.

Ejemplo 3:combinar semilla y no semilla en la misma consulta (múltiples llamadas RAND())

Debe tener cuidado al llamar a RAND() varias veces en la misma conexión. Si llamas a RAND() con un valor semilla especificado, todas las llamadas subsiguientes de RAND() producir resultados basados ​​en el RAND() sembrado llamar.

Por lo tanto, sin darse cuenta podría pensar que está ejecutando RAND() de forma no determinista cuando en realidad no lo eres.

Aquí hay un ejemplo para demostrarlo.

SELECT 
  RAND(100) AS [With Seed], 
  RAND() AS [No Seed], 
  RAND() AS [No Seed]
UNION ALL
SELECT 
  RAND(100) AS [With Seed], 
  RAND() AS [No Seed], 
  RAND() AS [No Seed]
UNION ALL
SELECT 
  RAND(100) AS [With Seed], 
  RAND() AS [No Seed], 
  RAND() AS [No Seed];

Resultado:

+-------------------+------------------+--------------------+
| With Seed         | No Seed          | No Seed            |
|-------------------+------------------+--------------------|
| 0.715436657367485 | 0.28463380767982 | 0.0131039082850364 |
| 0.715436657367485 | 0.28463380767982 | 0.0131039082850364 |
| 0.715436657367485 | 0.28463380767982 | 0.0131039082850364 |
+-------------------+------------------+--------------------+

Aunque el valor resultante es diferente en las columnas, cada llamada "sin semilla" en realidad se basó en la llamada "con semilla" y, por lo tanto, determinista.

Si mezclo las llamadas de función, esto es lo que obtengo.

SELECT 
  RAND() AS [No Seed], 
  RAND() AS [No Seed],
  RAND(100) AS [With Seed]
UNION ALL
SELECT 
  RAND() AS [No Seed], 
  RAND() AS [No Seed],
  RAND(100) AS [With Seed]
UNION ALL
SELECT 
  RAND() AS [No Seed], 
  RAND() AS [No Seed],
  RAND(100) AS [With Seed];

Resultado:

+------------------+--------------------+-------------------+
| No Seed          | No Seed            | With Seed         |
|------------------+--------------------+-------------------|
| 0.28769876521071 | 0.100505471175005  | 0.715436657367485 |
| 0.28463380767982 | 0.0131039082850364 | 0.715436657367485 |
| 0.28463380767982 | 0.0131039082850364 | 0.715436657367485 |
+------------------+--------------------+-------------------+