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

posted on 2020-05-07 09:44  jack_Meng  阅读(12825)  评论(0编辑  收藏  举报

导航