视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
SQLServer中的RAND函数的介绍和区间随机数值函数的实现
2020-11-09 07:02:43 责编:小采
文档


工作中会遇到SQL Server模拟数据生成以及数值列值(如整型、日期和时间数据类型)随机填充等等任务,这些任务中都要使用到随机数。鉴于此,本文将对SQL Server中随机数的使用简单做个总结 。

T-SQL 随机有关的三个函数

   RAND([seed] 此函数生成从0到1之间随机 float 值(详细说明查看https://technet.microsoft.com/zh-cn/library/ms177610(v=sql.90).aspx)。

    CHECKSUM ( * | expression [ ,...n ] ) 此函数生成按照表的某一行或一组表达式计算出来的int校验和值,CHECKSUM 用于生成哈希索引(详细说明查看https://technet.microsoft.com/zh-cn/library/ms1788(v=sql.90).aspx)。

    NEWID ( ) 此函数生成 uniqueidentifier 类型的唯一值(详细说明查看https://technet.microsoft.com/zh-cn/library/ms190348(v=sql.90).aspx)。

生成任意一个随机数值(如整数、日期和时间数据类型)

    如果获得任意一个随机整数值?函数RAND生成的结果是float数据类型的,显然很难满足要求,不过可以通过对函数RAND的结果继续加工(比如其结果乘以某一个值保留整数部分等等)得到要求。很显然,函数CHECKSUM生成的结果是int数据类型,很容易满足我们的结果,不过其参数如果固定(表的某一行值相同或一组表达式值相同),那么其结果也是相同的。函数NEWID可以保证结果的唯一,但是其结果是unigueidentifer数据类型的。

    从以上三个函数的结果值分析:函数RNAD和CHECKSUM的结果是能获得整数数值的。如果我们将函数NEWID的结果值作为函数CHECKSUM的参数,那么其每次生成的结果值都是不一样的int数据类型的数值。以下T-SQL代码如下:

SELECT CHECKSUM(NEWID()) AS CheckSumValue, CHECKSUM(NEWID()) AS CheckSumValue2;
GO

执行后的查询结果如下:

 

从上面的查询结果看到组合生成的整数数值都是9位数的,平时工作中大多使用的随机整数值都是不太大的且都是自然数(0和正整数的集合),这就要求随机生成的整数数值。可以使用函数ABS对其结果进行处理得到任意一个自然数。这样,组合一起来的格式就是这样的:ABS(CHECKSUM(NEWID()))。为了便于使用便于使用我们通过将其封装到函数中,但是函数NEWID又不能在函数中使用,那我们就要考虑其他的方式:将函数NEWID封装在单列单行的视图中。其定义视图的T-SQL代码如下:

 IF OBJECT_ID(N'dbo.vRandomGuid', 'V') IS NOT NULL
 BEGIN
 DROP VIEW dbo.vRandomGuid;
 END
 GO
 --==================================
 -- 功能: 随机Guid视图
 -- 说明: 具体实现阐述 
 -- 作者: XXX
 -- 创建: yyyy-MM-dd
 -- 修改: yyyy-MM-dd XXX 修改内容描述
 --==================================
 CREATE VIEW dbo.vRandomGuid
 --$Encode$--
 AS
 SELECT RandomGuid = NEWID();
 GO
 调用该视图的T-SQL代码如下:
 SELECT TOP RandomGuid
 FROM dbo.vRandomGuid;
 GO 

执行后的查询结果如下:

生成整数区间内的任意一个随机整数

上面的视图定义,我们继续讲解组合函数的进一步封装。我们先讲解如何随机生成的数值,取模运算可以实现生成在指定数值区间内的任意一个数值,例如:获取区间[3,5]内任意一个数字,我们设为区间的最小值为@intMin:3,最大值为@intMax,则该区间的间隔值为 @intMax - @intMin + 1: 5 - 3 + 1(3),那么针对任意的整数值设为为@intValue,然后对这个间隔值先进行取模运算在加上区间最小值,最后得到的值为: @intValue % (@intMax - @intMin + 1) + @intMin。如果@intValue为8,则结果值为5;如果@intValue为9,则结果值为3;如果@intValue为10,则结果值为4……

    针对以上的分析我们封装的T-SQL代码如下:

 IF OBJECT_ID(N'dbo.ufn_RandNum', 'FN') IS NOT NULL
 BEGIN
 DROP FUNCTION dbo.ufn_RandNum;
 END
 GO
 --==================================
 -- 功能: 获取区间内的任意一个随机数值
 -- 说明: 具体实现阐述 
 -- 作者: XXX
 -- 创建: yyyy-MM-dd
 -- 修改: yyyy-MM-dd XXX 修改内容描述
 -- 调用: SELECT dbo.ufn_RandNum(, );
 --==================================
 CREATE FUNCTION dbo.ufn_RandNum
 (
 @intMin INT, -- 随机数值的最小值
 @intMax INT -- 随机数值的最大值
 ) RETURNS INT
 --$Encode$--
 AS
 BEGIN 
 SET @intMin = ISNULL(@intMin, );
 SET @intMax = ISNULL(@intMax, );
 DECLARE @guidValue AS UNIQUEIDENTIFIER;
 SELECT TOP @guidValue = RandomGuid
 FROM dbo.vRandomGuid;
 RETURN ABS(CHECKSUM(@guidValue)) % (@intMax - @intMin + ) + @intMin;
 END
 GO 

调用以上函数的T-SQL代码如下:

 SELECT dbo.ufn_RandNum(, ) AS RandNum, dbo.ufn_RandNum(, ) AS RandNum;
 GO 

执行后的查询结果如下:

 

生成日期区间内的任意一个随机日期

    那么我们继续讲解 获取指定区间内的任意一个随机日期,不过我们要使用日期和时间的两个函数:DATEADD和DATEDIFF。使用DATEDIFF计算出日期区间的间隔值,同上的思路我们计算得到的一个随机整数值,然后通过DATEADD得到我们期望的一个随机日期。封装函数的T-SQL代码如下:

 IF OBJECT_ID(N'dbo.ufn_RandDate', 'FN') IS NOT NULL
 BEGIN
 DROP FUNCTION dbo.ufn_RandDate;
 END
 GO
 --==================================
 -- 功能: 获取日期区间内的任意一个随机日期
 -- 说明: 具体实现阐述 
 -- 作者: XXX
 -- 创建: yyyy-MM-dd
 -- 修改: yyyy-MM-dd XXX 修改内容描述
 -- 调用: SELECT @dtmRand = dbo.ufn_RandDate('--', '--');
 --==================================
 CREATE FUNCTION dbo.ufn_RandDate 
 (
 @dtmMin DATETIME, -- 随机日期的最小值
 @dtmMax DATETIME -- 随机日期的最大值
 ) RETURNS DATETIME
 --$Encode$--
 AS
 BEGIN
 SET @dtmMin = ISNULL(@dtmMin, '--');
 SET @dtmMax = ISNULL(@dtmMax, '--');
 DECLARE @guidVue AS UNIQUEIDENTIFIER;
 SELECT TOP @guidVue = RandomGuid 
 FROM dbo.vRandomGuid;
 -- 可以将HOUR换为DAYS
 RETURN DATEADD(HOUR, (ABS(CHECKSUM(@guidVue)) % ( + DATEDIFF(HOUR, @dtmMax, @dtmMin))), @dtmMin);
 END
 GO 

调用以上函数的T-SQL代码如下:

 SELECT dbo.ufn_RandDate('--', '--') AS RandDate, dbo.ufn_RandDate('--', '--') AS RandDate;
 GO 

执行后的查询结果如下:

 

 区间随机数获取的扩展思考

    无论是获取数值区间内的随机数值,还是日期区间内的随机日期,我们都使用了视图vRandomGuid。如果有一个连续的数值序列,我们通过查询这个数值序列,结合我们的区间数值和随机排序,也可以实现以上的效果。

    假设该数值序列为SeqDataTable(Num INT),数值区间[@intMin,@intMax],那么该数值区间任意一个随机数值的T-SQL代码如下:

 SELECT TOP Num
 FROM dbo.SeqDataTable
 WHERE Num BETWEEN @intMin AND @intMax
 ORDER BY NEWID() ASC; 

    当然也可以利用以上的数字序列SeqDataTable(Num INT),日期区间[@dtmMin,@dtmMax],那个该数字区间任意一个随机日期的T-SQL代码如下:

 SELECT TOP DATEADD(DAY, Num, @dtmMin)
 FROM dbo.SeqDataTable
 WHERE Num BETWEEN AND DATEDIFF(DAY, @dtmMax, @dtmMin)
 ORDER BY NEWID() ASC; 

 注意:以上代码无法执行成功的,也算是伪代码的。

您可能感兴趣的文章:

  • javascript Math.random()随机数函数
  • php数组函数序列 之shuffle()和array_rand() 随机函数使用介绍
  • Oracle随机函数之dbms_random使用详解
  • PHP中函数rand和mt_rand的区别比较
  • 生成随机数rand函数的用法详解
  • js生成随机数之random函数随机示例
  • php使用array_rand()函数从数组中随机选择一个或多个元素
  • 使用js Math.random()函数生成n到m间的随机数字
  • 下载本文
    显示全文
    专题