Генеруйте випадкове значення int від 3 до 6


101

Чи можливо в Microsoft SQL Server генерувати випадкові значення int від Min до Max (3-9 приклад, 15-99 тощо)

Я знаю, я можу генерувати від 0 до Max, але як збільшити границю Min?

Цей запит генерує випадкове значення від 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

1
Відповідь, що там у вас, працює, лише якщо у вас є дозволи адміністратора. Я обходив це шляхом використання первинного ключа на полі як насіння. Розподіл був не блискучим, але він слугував меті.
Тінь

Відповіді:


196

Це генерує випадкове число між 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 ( %) ділиться на це число і повертає решту (макс. значення max на одиницю менше, ніж число, яке ви використовуєте)
  • ABS змінює негативні результати на позитивні
  • потім додайте один до результату, щоб усунути 0 результатів (для імітації рулону з кістки)

2
це допомогло мені тонну! просто пам’ятайте, якщо ви намагаєтеся генерувати випадкові ключі для масових вставок, це може призвести до дублікатів, а деякі заяви не вдасться. але дякую!
Ніклас

3
Що робити, якщо мені доведеться генерувати випадкове число між 1 і 27? тобто діапазон більше 9?
somegeek

4
Якщо я дотримуюся логіки, то, здається, ця настройка точно дозволить вам легко динамічно встановити діапазон. ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min. Кілька тестів з мого боку дали хороші результати. Якщо це дійсно точно, я думаю, що цю відповідь можна було б трохи покращити, включивши її.
Ейлерт Гельмесет

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

Приємно і просто, з сайту 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

(Я зробив невелику зміну до @ Upper-, щоб включити верхнє число, додав 1.)


Я бачив цей приклад в іншій публікації. Він не забезпечує випадкового розподілу. Наприклад, нижній - 1, а верхній - 11, тому я хочу, щоб випадкові числа були від 1 до 10. 1 і 10 отримують половину випадків як 2-8. Іди і тестуй.
нанонерд

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
Хоча цей фрагмент коду вітається і може надати деяку допомогу, він би значно покращився, якби він включив пояснення того, як він вирішує питання. Без цього ваша відповідь має набагато меншу освітянську цінність - пам’ятайте, що ви відповідаєте на запитання читачів у майбутньому, а не лише про людину, яка зараз запитує! Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються.
Toby Speight

4

Ось простий і єдиний рядок коду

Для цього використовуйте функцію SQL Inbuild RAND () .

Ось формула для генерації випадкових чисел між двома числами (RETURN INT діапазон)

Тут a - ваше перше число (Min), а b - друге число (max) у діапазоні

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

Примітка: Ви можете використовувати функцію CAST або CONVERT, щоб отримати номер діапазону INT.

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

Приклад:

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

Ось формула для генерації випадкових чисел між двома числами (РОЗВ'ЯЗКИ ДЕКІМАЛЬНОГО РОЗВИТКУ)

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

Приклад:

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

Детальніше перевірити це: https://www.techonthenet.com/sql_server/functions/rand.php


1
Зауважте, як зазначено у зв'язаній статті, це фактично не генерує значення = Макс. Для цього, наприклад, для значень> = 10 і <= 25 вам знадобиться ВИБІРИТЬ ПІД (RAND () * (25-10 + 1)) + 10
Shaun

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

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;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.