Generieren Sie einen zufälligen int-Wert von 3 bis 6


101

Ist es in Microsoft SQL Server möglich, einen zufälligen int-Wert von Min bis Max zu generieren (Beispiel 3-9, 15-99 usw.)

Ich weiß, ich kann von 0 bis Max generieren, aber wie kann ich die Min-Grenze erhöhen?

Diese Abfrage generiert einen zufälligen Wert von 1 bis 6. Sie muss von 3 auf 6 geändert werden.

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

5 Sek. Später hinzugefügt :

Dumme Frage, sorry ...

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

1
Die Antwort, die Sie dort haben, funktioniert nur, wenn Sie über Administratorrechte für die Tabelle verfügen. Ich habe das umgangen, indem ich den Primärschlüssel auf dem Feld als Startwert verwendet habe. Die Verteilung war nicht brillant, aber sie hat den Zweck erfüllt.
Schatten

Antworten:


195

Dies erzeugt eine Zufallszahl zwischen 0-9

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

1 bis 6

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

3 bis 6

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

Dynamisch (basierend auf Eilert Hjelmeseths Kommentar)

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

Basierend auf Kommentaren aktualisiert:

  • NEWID generiert eine zufällige Zeichenfolge (für jede Zeile im Gegenzug)
  • CHECKSUM Nimmt den Wert der Zeichenfolge und erstellt eine Zahl
  • modulus ( %) dividiert durch diese Zahl und gibt den Rest zurück (was bedeutet, dass der maximale Wert eins weniger ist als die von Ihnen verwendete Zahl).
  • ABS ändert negative Ergebnisse in positive
  • Fügen Sie dann eins zum Ergebnis hinzu, um 0 Ergebnisse zu eliminieren (um einen Würfelwurf zu simulieren).

2
das hat mir eine Menge geholfen! Denken Sie daran, wenn Sie versuchen, zufällige Schlüssel für Masseneinfügungen zu generieren, kann dies zu Duplikaten führen und einige Anweisungen schlagen fehl. aber danke!
Niklas

3
Was ist, wenn ich eine Zufallszahl zwischen 1 und 27 generieren muss? dh Bereich größer als 9?
Somegeek

4
Wenn ich der Logik folge, können Sie mit dieser Optimierung den Bereich auf einfache Weise dynamisch einstellen. ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min. Einige Tests meinerseits ergaben gute Ergebnisse. Wenn es tatsächlich richtig ist, könnte diese Antwort meiner Meinung nach leicht verbessert werden, indem sie aufgenommen wird.
Eilert Hjelmeseth

13

Ich sehe, dass Sie eine Antwort auf Ihre Frage in SQL Server 2008 hinzugefügt haben, die Sie auch tun können

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

Einige Nachteile dieser Methode sind

  1. Dies ist langsamer als die NEWID()Methode
  2. Obwohl es einmal pro Zeile ausgewertet wird, erkennt der Abfrageoptimierer dies nicht, was zu ungeraden Ergebnissen führen kann .

aber ich dachte nur, ich würde es als eine weitere Option hinzufügen.


1
@ FSou1 - Ja. Ich denke, es CRYPT_GEN_RANDOMist wirklich für Situationen gedacht, in denen Sie eine kryptografisch sicherere Pseudozufallszahl benötigen.
Martin Smith

7

Du kannst das:

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

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

Und das wurde direkt von diesem Link übernommen . Ich weiß nicht wirklich, wie ich diese Antwort richtig würdigen soll.


5

Schön und einfach, von Pinal Daves Seite:

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

(Ich habe eine geringfügige Änderung am @ Upper- vorgenommen, um die obere Zahl aufzunehmen, hinzugefügt 1.)


Ich habe dieses Beispiel in einem anderen Beitrag gesehen. Es wird keine zufällige Verteilung bereitgestellt. ZB ist Lower 1 und Upper ist 11, also möchte ich Zufallszahlen von 1 bis 10. Die 1 und die 10 erhalten die Hälfte der Vorkommen als 2-8. Probieren Sie es aus.
Nanonerd

4

Einfach:

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.

Sie können diesen Code nach Ihren Wünschen ändern und bearbeiten.


1
Während dieser Code - Schnipsel zu begrüßen ist, und etwas Hilfe bieten kann, würde es erheblich verbessert , wenn es eine Erklärung enthalten von , wie es um die Frage anspricht. Ohne das hat Ihre Antwort einen viel geringeren pädagogischen Wert - denken Sie daran, dass Sie die Frage in Zukunft für die Leser beantworten, nicht nur für die Person, die jetzt fragt! Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen, und geben Sie an, welche Einschränkungen und Annahmen gelten.
Toby Speight

4

Hier ist die einfache und einzelne Codezeile

Verwenden Sie dazu die SQL Inbuild RAND () -Funktion.

Hier ist die Formel zum Generieren einer Zufallszahl zwischen zwei Zahlen (RETURN INT Range)

Hier ist a Ihre erste Zahl (Min) und b die zweite Zahl (Max) im Bereich

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

Hinweis: Sie können auch die CAST- oder CONVERT-Funktion verwenden, um die INT-Bereichsnummer abzurufen.

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

Beispiel:

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

Hier ist die Formel zum Generieren einer Zufallszahl zwischen zwei Zahlen (RETURN DECIMAL Range)

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

Beispiel:

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

Weitere Details finden Sie hier: https://www.techonthenet.com/sql_server/functions/rand.php


1
Beachten Sie, dass, wie im verlinkten Artikel erwähnt, keine Werte = max. Um dies zum Beispiel für Werte> = 10 und <= 25 zu tun, benötigen Sie SELECT FLOOR (RAND () * (25-10 + 1)) + 10
Shaun

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

2
Die Chance, eine Zahl über die andere zu bekommen, ist nicht gleichmäßig verteilt. Überprüfen Sie die Ausgabe von diesem: 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) Zeigt, dass 16% Änderung für 6, ~ 34% es ist 5, ~ 34% es ist 4 und ~ 16% es ist 3.
Mike de Klerk

Abschneiden ist dem Runden überlegen
MichaelChirico

0

Lamaks Antwort als Funktion:

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

Schritt für Schritt

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;

Beachten Sie, dass eine benutzerdefinierte Funktion die Verwendung von RAND () nicht zulässt. Eine Problemumgehung hierfür (Quelle: http://blog.sqlauthority.com/2012/11/20/sql-server-using-rand-in-user-defined-functions-udf/ ) besteht darin, zuerst eine Ansicht zu erstellen.

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

und erstellen Sie dann die Zufallsfunktion

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

Allgemein:

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

Für Ihre Frage:

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

<=>

select rand()*3+3;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.