T-SQL Ninja #51

RAND

Was ist RAND?

Die RAND-Funktion liefert euch – wenig überraschend – Zufallszahlen und gehört auch zu den am häufigsten verwendeten Funktionen in T-SQL. Dabei ist die RAND-Funktion ein wenig speziell, weshalb wir uns im Folgenden ansehen wollen, wie sie sich in bestimmten Szenarien verhält.

Wie könnt ihr mit RAND arbeiten?

Beginnen wir damit, dass ihr eine einfache Zufallszahl generiert. Folgender Aufruf gibt euch eine zufällige Zahl zwischen null und eins zurück:

SELECT RAND()

Wenn ihr diese Abfrage mehrfach ausführt, bekommt ihr jedes Mal eine neue Zahl. Versuchen wir nun, mehrere Zufallszahlen in eine Tabelle zu schreiben. Dafür legen wir uns zunächst eine temporäre Tabelle an:

DROP TABLE IF EXISTS #Randomness
CREATE TABLE #Randomness (
    MyNumber Decimal(10,2) 
)

Nun versuchen wir, zufällige Zahlen einzufügen:

INSERT INTO #Randomness 
(MyNumber)
VALUES 
(RAND()), (RAND()), (RAND())

SELECT * FROM #Randomness

Nun habt ihr aber die Möglichkeit, der RAND-Funktion einen sogenannten „Seed“ zu übergeben, also eine Zahl auf deren Basis die Zufallszahlen ermittelt werden. Tun wir das nun in unserem Beispiel:

INSERT INTO #Randomness 
(MyNumber)
VALUES 
(RAND(100)), (RAND()), (RAND())

INSERT INTO #Randomness 
(MyNumber)
VALUES 
(RAND(100)), (RAND()), (RAND())

SELECT * FROM #Randomness

Als Resultat dieser beiden INSERT-Statements seht ihr nun nicht sechs komplett zufällige Zahlen in euerer Tabelle sondern drei zufällige Zahlen, die jeweils zweimal eingefügt werden. Das bedeutet, dass ihr durch das Festlegen des Seed-Wertes die Abfolge der Zufallszahlen festlegt. Entfernt ihr beim zweiten INSERT-Statement den Seed, so erhaltet ihr hier wirklich zufällige Zahlen. Typischerweise ist der Rückgabewert von RAND eine Gleitkommazahl vom Typ float und einem Wertebereich zwischen 0 und 1. Wenn ihr größere Werte zurückbekommen möchtet, müsst ihr entsprechend skalieren, indem ihr multipliziert mit dem Maximalwert, der euch interessiert (oder dem doppelten Maximalwert, falls ihr auch negative Ergebnisse sehen möchtet). So erzeugt ihr also Zufallszahlen zwischen 0 und 10:

INSERT INTO #Randomness 
(MyNumber)
VALUES 
(10*RAND()), (10*RAND()), (10*RAND())

SELECT * FROM #Randomness

Und um Werte zwischen -5 und 5 zu bekommen, subtrahiert ihr noch 5 vom Resultat:

INSERT INTO #Randomness 
(MyNumber)
VALUES 
((10*RAND())-5.0), ((10*RAND())-5.0), ((10*RAND())-5.0)

SELECT * FROM #Randomness

Wenn euch nun ganzzahlige Zufallszahlen interessieren:

INSERT INTO #Randomness 
(MyNumber)
VALUES 
 (CAST(((10*RAND())-5.0) AS INT))
,(CAST(((10*RAND())-5.0) AS INT)) 
,(CAST(((10*RAND())-5.0) AS INT))

SELECT * FROM #Randomness

Und natürlich könnt ihr über RAND auch zufällige Datumswerte generieren. Hier erzeugt ihr ein zufälliges Datum das im letzten Jahr liegt, wobei der Zeit-Anteil der Datetime-Spalte immer dem Zeit-Anteil der Ausführung entspricht:

DECLARE @startdate datetime = DATEADD(Year, -1, GETDATE())
DECLARE @enddate datetime = GETDATE()

SELECT DATEADD(DAY, RAND()*DATEDIFF(DAY, @startdate, @enddate), @startdate)

Wenn ihr auch die Zeit randomisieren möchtet, dann ersetzt ihr einfach DAY durch SECOND:

DECLARE @startdate datetime = DATEADD(Year, -1, GETDATE())
DECLARE @enddate datetime = GETDATE()

SELECT DATEADD(SECOND, RAND()*DATEDIFF(SECOND, @startdate, @enddate), @startdate)

Sortieren könnt ihr in zufälliger Reihenfolge übrigens nicht mit der RAND-Funktion, denn die folgende Abfrage liefert immer wieder dieselbe Sortierung:

SELECT MyNumber
FROM #Randomness
ORDER BY RAND()

Stattdessen könnt ihr hier anders vorgehen und nach einem Wert sortieren, der zufällig generiert wird:

SELECT MyNumber
FROM #Randomness
ORDER BY NEWID()

Ihr habt heute im Dojo gelernt, wie ihr zufällige Werte im SQL Server erzeugt und verwendet. Die Zahlen mögen zufällig sein, gutes SQL ist es definitiv nicht…

Referenzen

Ninja-Notebooks @ GitHub

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.