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.