Genera un valore int casuale da 3 a 6


101

È possibile in Microsoft SQL Server generare un valore int casuale da Min a Max (3-9 esempio, 15-99 ecc.)

Lo so, posso generare da 0 a Max, ma come aumentare il bordo Min?

Questa query genera un valore casuale da 1 a 6. È necessario modificarlo da 3 a 6.

SELECT table_name, 1.0 + floor(6 * RAND(convert(varbinary, newid()))) magic_number 
FROM information_schema.tables

Aggiunto 5 secondi dopo :

Domanda stupida, scusa ...

SELECT table_name, 3.0 + floor(4 * RAND(convert(varbinary, newid()))) magic_number 
FROM information_schema.tables

1
La risposta che hai lì funziona solo se hai autorizzazioni di tipo amministratore sul tavolo. Il modo in cui ho aggirato questo problema è stato utilizzando la chiave primaria sul campo come seme. La distribuzione non è stata brillante, ma è servita allo scopo.
— Shadow

Risposte:


196

Questo genera un numero casuale compreso tra 0-9

SELECT ABS(CHECKSUM(NEWID()) % 10)

Da 1 a 6

SELECT ABS(CHECKSUM(NEWID()) % 6) + 1

Da 3 a 6

SELECT ABS(CHECKSUM(NEWID()) % 4) + 3

Dinamico (basato sul commento di Eilert Hjelmeseth)

SELECT ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min

Aggiornato in base ai commenti:

  • NEWID genera una stringa casuale (per ogni riga in cambio)
  • CHECKSUM prende il valore della stringa e crea il numero
  • modulo ( %) divide per quel numero e restituisce il resto (il che significa che il valore massimo è uno in meno del numero che usi)
  • ABS cambia i risultati negativi in ​​positivi
  • quindi aggiungine uno al risultato per eliminare 0 risultati (per simulare un lancio di dadi)

2
questo mi ha aiutato tantissimo! ricorda solo che se stai cercando di generare chiavi casuali per inserimenti in blocco, questo può causare duplicati e alcune istruzioni falliranno. ma grazie!
— Niklas

3
E se dovessi generare un numero casuale compreso tra 1 e 27? cioè intervallo maggiore di 9?
— somegeek

4
Se sto seguendo la logica, sembra che questo tweak ti consentirà di impostare facilmente l'intervallo in modo dinamico. ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min. Alcuni test da parte mia hanno dato buoni risultati. Se è davvero accurato, penso che questa risposta potrebbe essere leggermente migliorata includendola.
— Eilert Hjelmeseth

13

Vedo che hai aggiunto una risposta alla tua domanda in SQL Server 2008 che puoi anche fare

SELECT 3 + CRYPT_GEN_RANDOM(1) % 4 /*Random number between 3 and 6*/ 
FROM ...

Un paio di svantaggi di questo metodo sono

  1. Questo è più lento del NEWID()metodo
  2. Anche se viene valutato una volta per riga, l'ottimizzatore di query non si rende conto di ciò che può portare a risultati dispari .

ma ho pensato di aggiungerlo come un'altra opzione.


1
@ FSou1 - Sì. Penso che CRYPT_GEN_RANDOMsia davvero inteso per situazioni in cui è necessario un numero pseudo casuale più crittograficamente sicuro.
— Martin Smith

7

Puoi farlo:

DECLARE @maxval TINYINT, @minval TINYINT
select @maxval=24,@minval=5

SELECT CAST(((@maxval + 1) - @minval) *
    RAND(CHECKSUM(NEWID())) + @minval AS TINYINT)

E questo è stato preso direttamente da questo link , non so davvero come dare il giusto merito per questa risposta.


5

Bello e semplice, dal sito di Pinal Dave:

http://blog.sqlauthority.com/2007/04/29/sql-server-random-number-generator-script-sql-query/

DECLARE @Random INT;
DECLARE @Upper INT;
DECLARE @Lower INT
SET @Lower = 3 ---- The lowest random number
SET @Upper = 7 ---- One more than the highest random number
SELECT @Random = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)
SELECT @Random

(Ho apportato una leggera modifica a @ Upper- per includere il numero superiore, aggiunto 1.)


Ho visto questo esempio in un altro messaggio. Non fornisce una distribuzione casuale. Ad esempio, Lower è 1 e Upper è 11, quindi voglio numeri casuali da 1 a 10. L'1 e il 10 ottengono la metà delle occorrenze come 2-8. Vai a provarlo.
— nanonerd

4

Semplicemente:

DECLARE @MIN INT=3; --We define minimum value, it can be generated.
DECLARE @MAX INT=6; --We define maximum value, it can be generated.

SELECT @MIN+FLOOR((@MAX-@MIN+1)*RAND(CONVERT(VARBINARY,NEWID()))); --And then this T-SQL snippet generates an integer between minimum and maximum integer values.

Puoi cambiare e modificare questo codice in base alle tue esigenze.


1
Sebbene questo frammento di codice sia il benvenuto e possa fornire qualche aiuto, sarebbe notevolmente migliorato se includesse una spiegazione di come risolve la domanda. Senza questo, la tua risposta ha molto meno valore educativo: ricorda che stai rispondendo alla domanda per i lettori in futuro, non solo per la persona che lo chiede ora! Si prega di modificare la risposta di aggiungere una spiegazione, e dare un'indicazione di ciò si applicano le limitazioni e le assunzioni.
— Toby Speight

4

Ecco la semplice e singola riga di codice

Per questo utilizzare la funzione SQL Inbuild RAND () .

Ecco la formula per generare un numero casuale tra due numeri (intervallo RETURN INT)

Qui a è il tuo primo numero (min) eb è il secondo numero (max) nell'intervallo

SELECT FLOOR(RAND()*(b-a)+a)

Nota: è possibile utilizzare anche la funzione CAST o CONVERT per ottenere il numero dell'intervallo INT.

(CAST (RAND () * (25-10) +10 AS INT))

Esempio:

SELECT FLOOR(RAND()*(25-10)+10);

Ecco la formula per generare un numero casuale tra due numeri (RETURN DECIMAL Range)

SELECT RAND()*(b-a)+a;

Esempio:

SELECT RAND()*(25-10)+10;

Maggiori dettagli controllare questo: https://www.techonthenet.com/sql_server/functions/rand.php


1
Nota, come menzionato nell'articolo collegato, questo non genererà effettivamente valori = Max. Per fare questo, ad esempio, per i valori> = 10 e <= 25, è necessario SELEZIONARE PIANO (RAND () * (25-10 + 1)) + 10
— Shaun

1
SELECT ROUND((6 - 3 * RAND()), 0)

2
La possibilità di ottenere un numero sull'altro non è equamente distribuita. Controlla l'output di questo: SELECT ROUND((6 - 3 * 0.16), 0) SELECT ROUND((6 - 3 * 0.17), 0) SELECT ROUND((6 - 3 * 0.5), 0) SELECT ROUND((6 - 3 * 0.51), 0) SELECT ROUND((6 - 3 * 0.83), 0) SELECT ROUND((6 - 3 * 0.84), 0) mostra che il 16% cambia per 6, ~ 34% è 5, ~ 34% è 4 e ~ 16% è 3.
— Mike de Klerk

il troncamento è superiore all'arrotondamento
— MichaelChirico

0

La risposta di Lamak in funzione:

-- Create RANDBETWEEN function
-- Usage: SELECT dbo.RANDBETWEEN(0,9,RAND(CHECKSUM(NEWID())))
CREATE FUNCTION dbo.RANDBETWEEN(@minval TINYINT, @maxval TINYINT, @random NUMERIC(18,10))
RETURNS TINYINT
AS
BEGIN
  RETURN (SELECT CAST(((@maxval + 1) - @minval) * @random + @minval AS TINYINT))
END
GO

0
DECLARE @min INT = 3;
DECLARE @max INT = 6;
SELECT @min + ROUND(RAND() * (@max - @min), 0);

Passo dopo passo

DECLARE @min INT = 3;
DECLARE @max INT = 6;

DECLARE @rand DECIMAL(19,4) = RAND();
DECLARE @difference INT = @max - @min;
DECLARE @chunk INT = ROUND(@rand * @difference, 0);
DECLARE @result INT = @min + @chunk; 
SELECT @result;

Notare che una funzione definita dall'utente quindi non consente l'uso di RAND (). Una soluzione alternativa per questo (fonte: http://blog.sqlauthority.com/2012/11/20/sql-server-using-rand-in-user-defined-functions-udf/ ) è creare prima una vista.

CREATE VIEW [dbo].[vw_RandomSeed]
AS
SELECT        RAND() AS seed

e quindi creare la funzione casuale

CREATE FUNCTION udf_RandomNumberBetween
(
    @min INT,
    @max INT
)
RETURNS INT
AS
BEGIN
    RETURN @min + ROUND((SELECT TOP 1 seed FROM vw_RandomSeed) * (@max - @min), 0);
END

0

In generale:

select rand()*(@upper-@lower)+@lower;

Per la tua domanda:

select rand()*(6-3)+3;

<=>

select rand()*3+3;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.