Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie man RAND() in SQL Server deterministisch macht

Der RAND() -Funktion in SQL Server gibt einen pseudozufälligen Gleitkommawert von 0 bis 1 (exklusiv) zurück.

Diese Funktion kann deterministisch oder nicht deterministisch sein, je nachdem, wie sie aufgerufen wird.

Deterministische Funktionen geben immer das gleiche Ergebnis für einen gegebenen Satz von Eingabewerten und bei gleichem Zustand der Datenbank zurück. Nicht deterministische Funktionen können mit demselben Satz von Eingabewerten ein anderes Ergebnis zurückgeben, selbst wenn der Datenbankstatus gleich bleibt.

Der RAND() Funktion kann auf zwei Arten aufgerufen werden; mit Samen und ohne Samen. Wenn Sie es ohne Seed aufrufen, ist es nicht deterministisch. Wenn Sie es mit einem Seed aufrufen, ist es deterministisch.

Mit anderen Worten, für einen bestimmten Seed-Wert ist das zurückgegebene Ergebnis immer gleich.

Aber es gibt einen Haken:Manchmal wird RAND() aufgerufen ohne Samen ist deterministisch. Ich erkläre dies weiter unten.

Syntax

Hier ist zunächst die Syntax:

RAND ( [ seed ] )

Die eckigen Klammern bedeuten, dass das Seed-Argument optional ist.

Beispiel 1 – Kein Seed

Hier rufe ich RAND() auf fünfmal ohne Samen.

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

Ergebnis:

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

Jede Zeile hat einen anderen Wert.

Beispiel 2 – Mit Samen

Hier führe ich dieselbe Abfrage aus, außer dass ich jedem Funktionsaufruf denselben Seed hinzufüge.

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)

Ergebnis:

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

In diesem Fall haben alle Zeilen denselben Wert.

Beispiel 3 – Kombinieren Sie Seed und No Seed in derselben Abfrage (mehrere RAND()-Aufrufe)

Beim Aufrufen von RAND() müssen Sie vorsichtig sein mehrmals in der gleichen Verbindung. Wenn Sie RAND() aufrufen mit einem angegebenen Startwert alle nachfolgenden Aufrufe von RAND() Ergebnisse basierend auf dem gesetzten RAND() erzeugen Forderung.

Sie könnten also versehentlich denken, dass Sie RAND() ausführen nicht deterministisch, obwohl Sie es tatsächlich nicht sind.

Hier ist ein Beispiel zur Veranschaulichung.

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

Ergebnis:

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

Auch wenn der resultierende Wert in den Spalten unterschiedlich ist, basierte jeder „No Seed“-Aufruf tatsächlich auf dem „With Seed“-Aufruf und war daher deterministisch.

Wenn ich die Funktionsaufrufe verschiebe, bekomme ich Folgendes.

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

Ergebnis:

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