sql >> Database >  >> RDS >> Sqlserver

Hoe RAND() deterministisch te maken in SQL Server

De RAND() functie in SQL Server retourneert een pseudo-willekeurige float-waarde van 0 tot en met 1, exclusief.

Deze functie kan deterministisch of niet-deterministisch zijn, afhankelijk van hoe deze wordt aangeroepen.

Deterministische functies retourneren altijd hetzelfde resultaat voor een bepaalde set invoerwaarden en met dezelfde status van de database. Niet-deterministische functies kunnen een ander resultaat opleveren met dezelfde set invoerwaarden en zelfs als de databasestatus hetzelfde blijft.

De RAND() functie kan op twee manieren worden aangeroepen; met een zaad en zonder een zaad. Als je het zonder zaad noemt, is het niet-deterministisch. Als je het met een zaadje noemt, is het deterministisch.

Met andere woorden, voor een gespecificeerde seed-waarde is het geretourneerde resultaat altijd hetzelfde.

Maar er is een probleem:soms roept u RAND() zonder een zaadje is deterministisch. Ik leg dit hieronder uit.

Syntaxis

Ten eerste, hier is de syntaxis:

RAND ( [ seed ] )

De vierkante haken betekenen dat het seed-argument optioneel is.

Voorbeeld 1 – Geen zaad

Hier noem ik RAND() vijf keer zonder zaadje.

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

Resultaat:

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

Elke rij heeft een andere waarde.

Voorbeeld 2 – Met Zaad

Hier voer ik dezelfde query uit, behalve dat ik hetzelfde zaad aan elke functieaanroep toevoeg.

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)

Resultaat:

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

In dit geval hebben alle rijen dezelfde waarde.

Voorbeeld 3 – Combineer Seed en No Seed in dezelfde zoekopdracht (meerdere RAND()-aanroepen)

Je moet voorzichtig zijn bij het aanroepen van RAND() meerdere keren in dezelfde verbinding. Als u RAND() . aanroept met een gespecificeerde seed-waarde, alle volgende aanroepen van RAND() resultaten produceren op basis van de geplaatste RAND() telefoongesprek.

U zou dus per ongeluk kunnen denken dat u RAND() . uitvoert niet-deterministisch, terwijl u dat in feite niet bent.

Hier is een voorbeeld om te demonstreren.

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

Resultaat:

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

Hoewel de resulterende waarde in de kolommen verschilt, was elke "no seed" -aanroep eigenlijk gebaseerd op de "with seed" -aanroep, en daarom deterministisch.

Als ik de functie-aanroepen door elkaar schud, krijg ik het volgende.

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

Resultaat:

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

  1. door komma's gescheiden lijst als een enkele tekenreeks, T-SQL

  2. Zoeken in volledige tekst in MySQL:The Good, the Bad and the Ugly

  3. Maak een "in plaats van" trigger in SQL Server

  4. Wat is het MySQL-equivalent van STUFF() in SQL Server?