สร้างค่า int แบบสุ่มจาก 3 ถึง 6


104

เป็นไปได้ไหมใน Microsoft SQL Server สร้างค่า int แบบสุ่มจากต่ำสุดถึงสูงสุด (ตัวอย่าง 3-9, 15-99 เป็นต้น)

ฉันรู้ว่าฉันสามารถสร้างจาก 0 ถึง Max แต่จะเพิ่ม Min border ได้อย่างไร?

คำค้นหานี้สร้างค่าสุ่มจาก 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
คำตอบที่คุณมีจะใช้ได้ก็ต่อเมื่อคุณมีสิทธิ์ประเภทผู้ดูแลระบบในตาราง วิธีที่ฉันทำได้คือการใช้คีย์หลักบนฟิลด์เป็นเมล็ดพันธุ์ การกระจายไม่ได้ยอดเยี่ยม แต่ตอบสนองวัตถุประสงค์
เงา

คำตอบ:


200

สิ่งนี้จะสร้างตัวเลขสุ่มระหว่าง 0-9

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

1 ถึง 6

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

3 ถึง 6

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

ไดนามิก (อิงตามความคิดเห็นของ Eilert Hjelmeseths อัปเดตเพื่อแก้ไขข้อบกพร่อง (+ ถึง -))

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

อัปเดตตามความคิดเห็น:

  • NEWID สร้างสตริงแบบสุ่ม (สำหรับแต่ละแถวในทางกลับกัน)
  • CHECKSUM รับค่าของสตริงและสร้างตัวเลข
  • โมดูลัส ( %) หารด้วยจำนวนนั้นและส่งกลับส่วนที่เหลือ (หมายถึงค่าสูงสุดคือหนึ่งน้อยกว่าจำนวนที่คุณใช้)
  • ABS เปลี่ยนผลลัพธ์เชิงลบเป็นบวก
  • จากนั้นเพิ่มหนึ่งในผลลัพธ์เพื่อกำจัด 0 ผลลัพธ์ (เพื่อจำลองการทอยลูกเต๋า)

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มีไว้สำหรับสถานการณ์ที่คุณต้องการหมายเลขสุ่มหลอกที่ปลอดภัยยิ่งขึ้น
Martin Smith

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

(ฉันทำการเปลี่ยนแปลงเล็กน้อยกับ @ บน - เพื่อรวมตัวเลขบนเพิ่ม 1)


ฉันเห็นตัวอย่างนี้ในโพสต์อื่น ไม่มีการแจกแจงแบบสุ่ม เช่นล่างคือ 1 และบนคือ 11 ดังนั้นฉันต้องการสุ่มตัวเลขจาก 1 ถึง 10 โดย 1 และ 10 จะได้ครึ่งหนึ่งของการเกิดขึ้นเป็น 2-8 ไปทดสอบกันเลย
nanonerd

5

เพียงแค่:

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

นี่คือหมายเลขแรกของคุณ (ต่ำสุด) และ b คือเลขที่สอง (สูงสุด) ในช่วง

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

หมายเหตุ: คุณสามารถใช้ฟังก์ชันแคสต์หรือแปลงได้เช่นกันเพื่อรับหมายเลขช่วง INT

(แคสต์ (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
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
Mike de Klerk

การตัดทอนดีกว่าการปัดเศษ
MichaelChirico

0

คำตอบของ Lamakเป็นฟังก์ชัน:

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.