SQLServer隨機數的獲取


SQLServer獲得隨機數有兩種方法:
一、使用rand獲得隨機數
二、使用Checksum結合NewID獲得隨機數

一、使用rand
(1)Rand()函數是系統自帶的獲取隨機數的函數,可以直接運行select rand() 獲取0~1之間的float型的數字,類似的,如果想獲得例如1~100之間的整數隨機數可以運行 select round(100*rand(),0)
eg:得到60~100的隨機數,小數點后保留兩位

DECLARE @NumBegin Int=60    --隨機數的最小值 
DECLARE @NumEnd Int=100     --隨機數的最大值 
DECLARE @Decimal Int=2      --保留小數點幾位 
SELECT @NumBegin+round((@NumEnd-@NumBegin)*rand(),@Decimal)

ROUND() 函數用於把數值字段舍入為指定的小數位數,是對數據進行制定精度的取值。(具體可參考數據幫助文檔或網上查用法)

如果將2改為-1,則變成獲取60~100之間的10的倍數的整數,原因在於:這里的round(表達式,長度,操作方式)函數會返回一個數值,舍入到指定的長度,這里的操作方式默認為0,操作方式為0遵循的是四舍五入,指定其他整數值則直接截斷。
(返回的數值和原數值的總位數始終沒有變化)
關於長度:舍入精度
a)如果長度為正數,則將數值舍入到長度指定的小數位數。
b)如果長度為負數,則將數值小數點左邊部分舍入到長度指定的長度。注意如果長度為負數,並且大於小數點前的數字個數,則將返回 0。
c)如果長度為負數並且等於小數點前的數字個數且操作方式為四舍五入時,最前面的一位小於5返回0,大於等於5會導致錯誤出現,如果操作方法不是四舍五入時則不會出現錯誤,返回結果一律為0。

(2)rand()函數用在函數內部會報錯“在函數內對帶副作用的運算符‘rand’的使用無效”,但可以通過作為參數傳參實現:
eg:

CREATE FUNCTION Scalar_CheckSumNEWIDQ ( @From int, @To int, @Keep int, @RAND float ) RETURNS float BEGIN RETURN @From+round((@To-@From)*@RAND,@Keep) END GO SELECT dbo.Scalar_CheckSumNEWIDQ(20,30,6,RAND())

這里即使參數相同,多次運行都可以得到范圍內不同的隨機數

 

(3)rand() + floor() + ceiling() 結合使用

在SQL Server中,有個隨機函數rand(),

在查詢分析器中執行:select rand(),可以看到結果會是類似於這樣的隨機小數:0.36361513486289558, 
像這樣的小數在實際應用中用得不多,一般要取隨機數都會取隨機整數。那就看下面的兩種隨機取整數的方法: 
(3.1)、 
A:select floor(rand()*N) ---生成的數是這樣的:12.0 
B:select cast( floor(rand()*N) as int) ---生成的數是這樣的:12 
(3.2)、 
A:select ceiling(rand() * N) ---生成的數是這樣的:12.0 
B:select cast(ceiling(rand() * N) as int) ---生成的數是這樣的:12 

其中里面的N是一個你指定生成結果的最大值的整數,如100,將生成0-100隨機數。可以看出,兩種方法的A方法是帶有.0這個的小數的,而B方法就是真正的整數了。 
大致一看,這兩種方法沒什么大的區別!真的沒區別?其實是有一點的,那就是他們的生成隨機數的范圍: 
方法1的數字范圍:0至N-1之間,如cast( floor(rand()*100) as int)就會生成0至99之間任一整數 
方法2的數字范圍:1至N之間,如cast(ceiling(rand() * 100) as int)就會生成1至100之間任一整數 
對於這個區別,看SQL的聯機幫助就知了: 
------------------------------------------------------------------------------------ 
比較 CEILING 和 FLOOR 
CEILING 函數返回大於或等於所給數字表達式的最小整數。

FLOOR 函數返回小於或等於所給數字表達式的最大整數。

例如,對於數字表達式 12.9273,CEILING 將返回 13,FLOOR 將返回 12。

注意:FLOOR 和 CEILING 返回值的數據類型都與輸入的數字表達式的數據類型相同。 
---------------------------------------------------------------------------------- 
另外,還要提示一下各位菜鳥,關於隨機取得表中任意N條記錄的方法,很簡單,就用newid(): 
select top N * from table_name order by newid() ----N是一個你指定的整數,表示取得記錄的條數 。
————————————————————————————————————————————————————————
原文鏈接:https://blog.csdn.net/u014053368/java/article/details/23976845

 

 


二、使用Checksum結合NewID
(1) Checksum:總和檢驗碼,校驗和。在數據處理和數據通信領域中,用於校驗目的的一組數據項的和。這些數據項可以是數字或在計算檢驗總和過程中看作數字的其它字符串。它通常是以十六進制為數制表示的形式,如果校驗和的數值超過十六進制的FF,也就是255. 就要求其補碼作為校驗和.通常用來在通信中,尤其是遠距離通信中保證數據的完整性和准確性

(2) 在SQLServer中Checksum()需要傳入1個參數,可以是任何類型
eg:

SELECT CHECKSUM(1)          --1 
SELECT CHECKSUM('A')        --114 
SELECT CHECKSUM('AA')       --34472462 
SELECT CHECKSUM(GETDATE())  --18516390

可以看出傳入不同參數就有不同的返回值,每個參數的返回值都是固定的,而且還有可能會出現負數的,並看不出有什么規律

(3)因此,我們可以通過傳入newid()來獲得隨機數,因為newid()每次獲得的值都是唯一的隨機的。
eg:

SELECT CHECKSUM(NEWID()) UNION ALL SELECT CHECKSUM(NEWID()) UNION ALL SELECT CHECKSUM(NEWID()) UNION ALL SELECT CHECKSUM(NEWID()) 

結果為:
這里寫圖片描述
注:這里的UNION ALL只是結果集的堆疊輸出,要與之區別的還有union:
1.union會去除結果集中重復的部分,相當於進行一個distinct(去重),並且union 會自帶排序功能;
2.union all 會不管是否重復,都會將結果合並在一起輸出,沒有排序功能,只是結果集的堆疊輸出
(4)在函數中的使用,也只能通過傳參的方法
eg:

CREATE FUNCTION aaa ( @From int, @To int, @Keep int, @newid varchar(50) ) RETURNS float BEGIN DECLARE @ResultVar float SELECT @ResultVar=CONVERT(BIGINT,RIGHT(ABS(CHECKSUM(@newid)),9))*0.1/100000000 RETURN @From+round((@To-@From)*@ResultVar,@Keep) END SELECT dbo.aaa(20,30,6,'NEWID()')

由於CHECKSUM()得到的數是固定的,所以同一組參數多次運行出現的結果是相同的

注:ABS() 絕對值函數
RIGHT(表達式,n) 取表達式從右數起n個字符
CONVERT() 數據類型轉換
9與*0.1/100000000 對應,使得@ResultVar隨機得到的數是0~1之間的數,類似於函數rand()的功能

三、兩種方法的比較

(1)稍加處理,CHECKSUM也可以當作rand來使用
eg:從結果看出都可以得到隨機數

SELECT CHECKSUM=CONVERT(BIGINT,RIGHT(ABS(CHECKSUM(NEWID())),9))*0.1/100000000 ,RAND=RAND() UNION ALL SELECT CHECKSUM=CONVERT(BIGINT,RIGHT(ABS(CHECKSUM(NEWID())),9))*0.1/100000000 ,RAND=RAND() UNION ALL SELECT CHECKSUM=CONVERT(BIGINT,RIGHT(ABS(CHECKSUM(NEWID())),9))*0.1/100000000 ,RAND=RAND() UNION ALL SELECT CHECKSUM=CONVERT(BIGINT,RIGHT(ABS(CHECKSUM(NEWID())),9))*0.1/100000000 ,RAND=RAND() 

結果為:
這里寫圖片描述
(2)但rand函數有個弊端,若我們想在一張表的每一元組后面生成一個唯一的隨機數時(即在表中添加一列隨機數),只能用CHECKSUM和NEWID來實現
原因在於:使用rand會出現相同的隨機數,然而這並不是我們想要的
eg:

 SELECT *,RAND() '隨機數' FROM Product

結果為:
這里寫圖片描述

SELECT *,NEWID() '隨機數' FROM Product

結果為:
這里寫圖片描述
類似的:

SELECT id ,CHECKSUM=CONVERT(BIGINT,RIGHT(ABS(CHECKSUM(NEWID())),9))*0.1/100000000 ,RAND=RAND() from Product

得到的結果是:
這里寫圖片描述

 

 

出處:https://blog.csdn.net/qq_41571267/article/details/80229900


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM