Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come rendere deterministico RAND() in SQL Server

Il RAND() funzione in SQL Server restituisce un valore float pseudocasuale compreso tra 0 e 1, esclusivo.

Questa funzione può essere deterministica o non deterministica, a seconda di come viene invocata.

Le funzioni deterministiche restituiscono sempre lo stesso risultato per un dato insieme di valori di input e dato lo stesso stato del database. Le funzioni non deterministiche possono restituire un risultato diverso con lo stesso insieme di valori di input e anche se lo stato del database rimane lo stesso.

Il RAND() la funzione può essere chiamata in due modi; con un seme e senza un seme. Se lo chiami senza seme, non è deterministico. Se lo chiami con un seme, è deterministico.

In altre parole, per un valore seed specificato, il risultato restituito è sempre lo stesso.

Ma c'è un problema:a volte chiamando RAND() senza seme è deterministico. Lo spiego di seguito.

Sintassi

Innanzitutto, ecco la sintassi:

RAND ( [ seed ] )

Le parentesi quadre indicano che l'argomento seme è facoltativo.

Esempio 1 – Nessun seme

Qui chiamo RAND() cinque volte senza seme.

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

Risultato:

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

Ogni riga ha un valore diverso.

Esempio 2 – Con seme

Qui eseguo la stessa query, tranne per il fatto che aggiungo lo stesso seme a ciascuna chiamata di funzione.

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)

Risultato:

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

In questo caso, tutte le righe hanno lo stesso valore.

Esempio 3 – Combina seme e nessun seme nella stessa query (più chiamate RAND())

Devi fare attenzione quando chiami RAND() più volte nella stessa connessione. Se chiami RAND() con un valore seme specificato, tutte le successive chiamate di RAND() produrre risultati basati sul RAND() seminato chiamata.

Quindi potresti inavvertitamente pensare che stai eseguendo RAND() in modo non deterministico quando in realtà non lo sei.

Ecco un esempio da dimostrare.

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];

Risultato:

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

Anche se il valore risultante è diverso nelle colonne, ogni chiamata "no seed" era in realtà basata sulla chiamata "with seed" e, quindi, deterministica.

Se metto in ordine casuale le chiamate di funzione, ecco cosa ottengo.

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];

Risultato:

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