Сгенерировать случайное значение int от 3 до 6

104

Возможно ли в Microsoft SQL Server сгенерировать случайное значение int от Min до Max (пример 3-9, 15-99 и т. Д.)

Я знаю, я могу сгенерировать от 0 до Max, но как увеличить минимальную границу?

Этот запрос генерирует случайное значение от 1 до 6. Необходимо изменить его с 3 на 6.

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

Добавлено через 5 секунд :

Глупый вопрос, извините ...

SELECT table_name, 3.0 + floor(4 * RAND(convert(varbinary, newid()))) magic_number 
FROM information_schema.tables
FSou1
источник
1
Ответ, который у вас есть, работает только в том случае, если у вас есть права администратора для таблицы. Я решил это обойти, используя первичный ключ поля в качестве начального числа. Распределение не было блестящим, но оно послужило цели.
Shadow

Ответы:

199

Это генерирует случайное число от 0 до 9.

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

С 1 по 6

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

С 3 по 6

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

Динамический (на основе комментария Эйлерта Хьельмесета)

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

Обновлено на основе комментариев:

  • NEWID генерирует случайную строку (для каждой строки в ответ)
  • CHECKSUM принимает значение строки и создает число
  • modulus ( %) делится на это число и возвращает остаток (то есть максимальное значение на единицу меньше, чем используемое вами число)
  • ABS меняет отрицательные результаты на положительные
  • затем добавьте единицу к результату, чтобы исключить 0 результатов (для имитации броска кубиков)
orgtigger
источник
2
это мне очень помогло! просто помните, что если вы пытаетесь сгенерировать случайные ключи для массовой вставки, это может привести к дублированию, и некоторые операторы не будут работать. но спасибо!
Niklas
3
Что, если мне нужно сгенерировать случайное число от 1 до 27? т.е. диапазон больше 9?
somegeek
4
Если я следую логике, кажется, что эта настройка точно позволит вам легко динамически устанавливать диапазон. ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min. Несколько тестов с моей стороны дали хорошие результаты. Если это действительно так, я думаю, что этот ответ можно немного улучшить, включив его.
Eilert Hjelmeseth
13

Я вижу, вы добавили ответ на свой вопрос в SQL Server 2008, вы также можете сделать

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

Пара недостатков этого метода:

  1. Это медленнее, чем NEWID()метод
  2. Несмотря на то, что он оценивается один раз для каждой строки, оптимизатор запросов не понимает этого, что может привести к нечетным результатам .

но просто подумал, что добавлю это как другой вариант.

Мартин Смит
источник
1
@ FSou1 - Да. Я думаю, CRYPT_GEN_RANDOMон действительно предназначен для ситуаций, когда вам нужно более криптографически безопасное псевдослучайное число.
Мартин Смит
7

Ты можешь сделать это:

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

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

И это было взято прямо из этой ссылки , я действительно не знаю, как отдать должное этому ответу.

Ламак
источник
5

Красиво и просто, с сайта Пинала Дэйва:

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

(Я немного изменил @ Upper-, чтобы включить верхнее число, добавил 1.)

Адриан Карр
источник
Я видел этот пример в другом посте. Он не обеспечивает случайного распределения. Например, нижний - 1, а верхний - 11, поэтому мне нужны случайные числа от 1 до 10. 1 и 10 получают половину случаев, как 2-8. Пойдите и проверьте это.
nanonerd
4

Просто:

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.

Вы можете изменить и отредактировать этот код под свои нужды.

МЕРТ ДОГАН
источник
1
Хотя этот фрагмент кода приветствуется и может оказать некоторую помощь, его можно было бы значительно улучшить, если бы он включал объяснение того, как он решает вопрос. Без этого ваш ответ имеет гораздо меньшую образовательную ценность - помните, что вы отвечаете на вопрос для читателей в будущем, а не только для человека, который задает сейчас! Пожалуйста , измените свой ответ , чтобы добавить объяснение, и дать указание о том , что применять ограничения и допущения.
Тоби Спейт
4

Вот простая и единственная строка кода

Для этого используйте SQL Inbuild RAND () .

Вот формула для генерации случайного числа между двумя числами (RETURN INT Range)

Здесь a - ваше первое число (мин.), А b - второе число (макс.) В диапазоне.

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

Примечание: вы также можете использовать функцию CAST или CONVERT, чтобы получить номер диапазона INT.

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

Пример:

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

Вот формула для генерации случайного числа между двумя числами (RETURN DECIMAL Range)

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

Пример:

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

Подробнее проверьте это: https://www.techonthenet.com/sql_server/functions/rand.php

Манджунатх Билвар
источник
1
Обратите внимание, как упоминалось в связанной статье, на самом деле это не будет генерировать значения = Макс. Для этого, например, для значений> = 10 и <= 25 вам потребуется SELECT FLOOR (RAND () * (25-10 + 1)) + 10
Шон
1
SELECT ROUND((6 - 3 * RAND()), 0)
greg121
источник
2
Шанс получить одно число над другим неравномерно. Проверьте результат: 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) показывает, что изменение на 16% для 6, ~ 34% это 5, ~ 34% это 4 и ~ 16% это 3.
Майк де Клерк
усечения превосходит округление
MichaelChirico
0

Ответ Ламака как функция:

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

Шаг за шагом

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;

Обратите внимание, что определяемая пользователем функция, таким образом, не позволяет использовать RAND (). Обходной путь для этого (источник: http://blog.sqlauthority.com/2012/11/20/sql-server-using-rand-in-user-defined-functions-udf/ ) - сначала создать представление.

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

а затем создайте случайную функцию

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

В основном:

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

На ваш вопрос:

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

<=>

select rand()*3+3;
Зейнаб
источник