Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment rendre RAND() déterministe dans SQL Server

Le RAND() La fonction dans SQL Server renvoie une valeur flottante pseudo-aléatoire comprise entre 0 et 1, exclusif.

Cette fonction peut être déterministe ou non déterministe, selon la façon dont elle est invoquée.

Les fonctions déterministes renvoient toujours le même résultat pour un ensemble donné de valeurs d'entrée et étant donné le même état de la base de données. Les fonctions non déterministes peuvent renvoyer un résultat différent avec le même ensemble de valeurs d'entrée et même si l'état de la base de données reste le même.

Le RAND() la fonction peut être appelée de deux manières ; avec une graine et sans graine. Si vous l'appelez sans graine, c'est non déterministe. Si vous l'appelez avec une graine, c'est déterministe.

En d'autres termes, pour une valeur de départ spécifiée, le résultat renvoyé est toujours le même.

Mais il y a un piège :appeler parfois RAND() sans graine est déterministe. Je l'explique ci-dessous.

Syntaxe

Tout d'abord, voici la syntaxe :

RAND ( [ seed ] )

Les crochets signifient que l'argument de départ est facultatif.

Exemple 1 – Pas de graine

Ici j'appelle RAND() cinq fois sans graine.

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

Résultat :

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

Chaque ligne a une valeur différente.

Exemple 2 – Avec graine

Ici, j'exécute la même requête, sauf que j'ajoute la même graine à chaque appel de fonction.

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)

Résultat :

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

Dans ce cas, toutes les lignes ont la même valeur.

Exemple 3 - Combiner Seed et No Seed dans la même requête (plusieurs appels RAND())

Vous devez être prudent lorsque vous appelez RAND() plusieurs fois dans la même connexion. Si vous appelez RAND() avec une valeur de départ spécifiée, tous les appels ultérieurs de RAND() produire des résultats basés sur le RAND() ensemencé appel.

Vous pourriez donc penser par inadvertance que vous exécutez RAND() de manière non déterministe alors qu'en fait vous ne l'êtes pas.

Voici un exemple pour illustrer.

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

Résultat :

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

Même si la valeur résultante est différente d'une colonne à l'autre, chaque appel "sans graine" était en fait basé sur l'appel "avec graine", et donc déterministe.

Si je mélange les appels de fonction, voici ce que j'obtiens.

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

Résultat :

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