Wygeneruj losową wartość int od 3 do 6


101

Czy w Microsoft SQL Server można wygenerować losową wartość int od Min do Max (przykład 3-9, 15-99 itd.)

Wiem, mogę wygenerować od 0 do Max, ale jak zwiększyć granicę Min?

To zapytanie generuje losową wartość od 1 do 6. Należy ją zmienić z 3 na 6.

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

Dodano 5 sekund później :

Głupie pytanie, przepraszam ...

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

1
Odpowiedź, którą tam masz, działa tylko wtedy, gdy masz uprawnienia administratora do tabeli. Sposób, w jaki sobie z tym poradziłem, polegał na użyciu klucza głównego na polu jako nasion. Dystrybucja nie była genialna, ale spełniła swoje zadanie.
Shadow

Odpowiedzi:


196

To generuje losową liczbę z przedziału od 0 do 9

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

Od 1 do 6

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

Od 3 do 6

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

Dynamiczny (na podstawie komentarza Eilerta Hjelmesethsa)

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

Zaktualizowano na podstawie komentarzy:

  • NEWID generuje losowy ciąg (dla każdego zwracanego wiersza)
  • CHECKSUM przyjmuje wartość łańcucha i tworzy liczbę
  • modulus ( %) dzieli przez tę liczbę i zwraca resztę (co oznacza, że ​​maksymalna wartość jest o jeden mniejsza niż liczba, której używasz)
  • ABS zmienia negatywne wyniki na pozytywne
  • następnie dodaj jeden do wyniku, aby wyeliminować 0 wyników (aby zasymulować rzut kośćmi)

2
to mi pomogło! pamiętaj tylko, że jeśli próbujesz wygenerować losowe klucze do wstawiania zbiorczego, może to spowodować duplikaty, a niektóre instrukcje zakończą się niepowodzeniem. ale dziękuję!
Niklas

3
Co jeśli muszę wygenerować losową liczbę od 1 do 27? tj. zakres większy niż 9?
somegeek

4
Jeśli podążam za logiką, wydaje się, że ta poprawka dokładnie pozwoli ci dynamicznie ustawić zakres z łatwością. ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min. Kilka testów z mojej strony dało dobre wyniki. Jeśli rzeczywiście jest dokładna, myślę, że tę odpowiedź można by nieco poprawić, włączając ją.
Eilert Hjelmeseth

13

Widzę, że dodałeś odpowiedź na swoje pytanie w SQL Server 2008, którą możesz również zrobić

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

Jest kilka wad tej metody

  1. Jest to wolniejsze niż NEWID()metoda
  2. Mimo że jest oceniany raz na wiersz, optymalizator zapytań nie zdaje sobie z tego sprawy, co może prowadzić do dziwnych wyników .

ale pomyślałem, że dodam to jako inną opcję.


1
@ FSou1 - Tak. Myślę, że CRYPT_GEN_RANDOMjest naprawdę przeznaczony do sytuacji, w których potrzebujesz bardziej bezpiecznej kryptograficznie liczby pseudolosowej.
Martin Smith

7

Możesz to zrobić:

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

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

I to zostało wzięte bezpośrednio z tego linku , naprawdę nie wiem, jak należycie przypisać tę odpowiedź.


5

Ładnie i prosto, ze strony 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

(Zrobiłem niewielką zmianę w @ Upper- aby uwzględnić wyższą liczbę, dodałem 1.)


Widziałem ten przykład w innym poście. Nie zapewnia losowej dystrybucji. Np. Dolny to 1, a Górny to 11, więc chcę losowych liczb od 1 do 10. 1 i 10 otrzymują połowę wystąpień jako 2-8. Idź i przetestuj to.
nanonerd

4

Po prostu:

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.

Możesz zmienić i edytować ten kod do swoich potrzeb.


1
Chociaż ten fragment kodu jest mile widziany i może stanowić pomoc, byłby znacznie ulepszony, gdyby zawierał wyjaśnienie, w jaki sposób odpowiada na pytanie. Bez tego Twoja odpowiedź ma znacznie mniejszą wartość edukacyjną - pamiętaj, że w przyszłości odpowiadasz na pytanie czytelnikom, a nie tylko osobie, która pyta teraz! Proszę edytować swoje odpowiedzi, aby dodać wyjaśnienie, i dać wskazówkę co zastosować ograniczenia i założenia.
Toby Speight

4

Oto prosta i pojedyncza linia kodu

W tym celu użyj funkcji SQL Inbuild RAND () .

Oto formuła generowania liczby losowej między dwiema liczbami (zakres RETURN INT)

Tutaj a to Twoja pierwsza liczba (Min), a b to druga liczba (Max) w zakresie

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

Uwaga: Możesz również użyć funkcji CAST lub CONVERT, aby uzyskać numer zakresu INT.

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

Przykład:

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

Oto formuła generowania liczby losowej między dwiema liczbami (zakres RETURN DECIMAL)

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

Przykład:

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

Więcej szczegółów sprawdź: https://www.techonthenet.com/sql_server/functions/rand.php


1
Uwaga, jak wspomniano w powiązanym artykule, nie wygeneruje to w rzeczywistości wartości = Max. Aby to zrobić, na przykład dla wartości> = 10 i <= 25, potrzebujesz SELECT FLOOR (RAND () * (25-10 + 1)) + 10
Shaun

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

2
Szansa na uzyskanie jednej liczby nad drugą nie jest równa. Sprawdź wynik: 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) pokazuje, że zmiana 16% na 6, ~ 34% to 5, ~ 34% to 4, a ~ 16% to 3.
Mike de Klerk

obcięcie jest lepsze niż zaokrąglanie
MichaelChirico

0

Odpowiedź Lamaka jako funkcja:

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

Krok po kroku

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;

Zauważ, że funkcja zdefiniowana przez użytkownika nie pozwala więc na użycie RAND (). Aby obejść ten problem (źródło: http://blog.sqlauthority.com/2012/11/20/sql-server-using-rand-in-user-defined-functions-udf/ ), najpierw należy utworzyć widok.

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

a następnie utwórz funkcję losową

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

Ogólnie:

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

Twoje pytanie:

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

<=>

select rand()*3+3;
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.