我表中的每一行都需要一个不同的随机数。以下看似显而易见的代码为每行使用相同的随机值。
SELECT table_name, RAND() magic_number
FROM information_schema.tables
我想从中获取整数或浮点数。故事的其余部分是我将使用该随机数创建一个相对于已知日期的随机日期偏移量,例如,相对于开始日期偏移1-14天。
这是用于Microsoft SQL Server 2000。
我表中的每一行都需要一个不同的随机数。以下看似显而易见的代码为每行使用相同的随机值。
SELECT table_name, RAND() magic_number
FROM information_schema.tables
我想从中获取整数或浮点数。故事的其余部分是我将使用该随机数创建一个相对于已知日期的随机日期偏移量,例如,相对于开始日期偏移1-14天。
这是用于Microsoft SQL Server 2000。
Answers:
看一下SQL Server-基于集合的随机数,其中有非常详细的说明。
总而言之,以下代码生成一个介于0到13之间(含0和13)且具有均匀分布的随机数:
ABS(CHECKSUM(NewId())) % 14
要更改范围,只需更改表达式末尾的数字即可。如果您需要同时包含正数和负数的范围,请格外小心。如果输入错误,则可以对数字0进行重复计数。
这是对房间中数学坚果的一个小警告:此代码中有一个非常小的偏差。CHECKSUM()
结果产生的数字在sql Int数据类型的整个范围内是统一的,或者至少与我的(编辑器)测试可以显示的数字一致。但是,当CHECKSUM()在该范围的最高端生成一个数字时,将存在一些偏差。每当您在最大可能整数与所需范围大小的最后一个精确倍数(在这种情况下为14)之间得到一个数字时,这些结果就会在范围内无法产生的其余部分受到青睐最后的14的倍数。
例如,假设Int类型的整个范围仅为19。19是您可以容纳的最大可能整数。当CHECKSUM()结果为14-19时,它们对应于结果0-5。这些数字将比6-13 更受青睐,因为生成CHECKSUM()的可能性是其两倍。直观地演示这一点比较容易。以下是我们虚数范围的所有可能结果集:
校验和整数:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 范围结果:0 1 2 3 4 5 6 7 8 9 10 11 12 13 0 1 2 3 4 5
您可以在这里看到产生一些数字的机会比其他数字更大:偏见。值得庆幸的是,Int类型的实际范围要大得多……以至于在大多数情况下,几乎无法检测到偏差。但是,如果您发现自己这样做是为了获得严格的安全代码,则要意识到这一点。
在一个批次中多次调用时,rand()返回相同的数字。
我建议使用convert(varbinary
,newid()
)作为种子参数:
SELECT table_name, 1.0 + floor(14 * RAND(convert(varbinary, newid()))) magic_number
FROM information_schema.tables
newid()
保证每次调用都返回一个不同的值,即使在同一批处理中也是如此,因此将其用作种子将提示rand()每次给出不同的值。
编辑以获取1到14之间的随机整数。
RAND(CHECKSUM(NEWID()))
上面的代码将生成一个介于0和1之间(伪)的(伪)随机数。如果在选择中使用,由于种子值会针对每一行而变化,因此它将为每一行生成一个新的随机数(但是,不能保证每行生成唯一的数)。
结合上限为10(产生数字1-10)的示例:
CAST(RAND(CHECKSUM(NEWID())) * 10 as INT) + 1
Transact-SQL文档:
在1000到9999之间的随机数生成:
FLOOR(RAND(CHECKSUM(NEWID()))*(9999-1000+1)+1000)
“ +1”-包括上限值(前面的示例为9999)
FLOOR(RAND(CHECKSUM(NEWID()))*(10000-1000)+1000)
回答旧问题,但是以前没有提供过此答案,希望这对通过搜索引擎找到此结果的人很有用。
在SQL Server 2008中,引入了一个新函数,该函数CRYPT_GEN_RANDOM(8)
使用CryptoAPI生成密码强的随机数,返回为VARBINARY(8000)
。这是文档页面: https //docs.microsoft.com/zh-cn/sql/t-sql/functions/crypt-gen-random-transact-sql
因此,要获得随机数,您只需调用函数并将其转换为必要的类型即可:
select CAST(CRYPT_GEN_RANDOM(8) AS bigint)
或获得float
介于-1和+1之间的值,您可以执行以下操作:
select CAST(CRYPT_GEN_RANDOM(8) AS bigint) % 1000000000 / 1000000000.0
在每一行中都有一个整数值可以作为种子传递给RAND函数吗?
为了获得1到14之间的整数,我相信这会起作用:
FLOOR( RAND(<yourseed>) * 14) + 1
RAND(<seed>)
可行的,但实际上,我发现对于的细微变化似乎并不是很随机<seed>
。例如,我做了一个快速测试:我<seed>
为184380、184383、184386,相应的RAND(<seed>)
值为:0.14912、0.14917、0.14923。
RAND(<seed>)*100000) - FLOOR(RAND(<seed>)*100000)
如果您需要保存您的种子,以便每次生成“相同的”随机数据,则可以执行以下操作:
1.创建一个返回select rand()的视图
if object_id('cr_sample_randView') is not null
begin
drop view cr_sample_randView
end
go
create view cr_sample_randView
as
select rand() as random_number
go
2.创建一个从视图中选择值的UDF。
if object_id('cr_sample_fnPerRowRand') is not null
begin
drop function cr_sample_fnPerRowRand
end
go
create function cr_sample_fnPerRowRand()
returns float
as
begin
declare @returnValue float
select @returnValue = random_number from cr_sample_randView
return @returnValue
end
go
3.在选择数据之前,请为rand()函数设置种子,然后在select语句中使用UDF。
select rand(200); -- see the rand() function
with cte(id) as
(select row_number() over(order by object_id) from sys.all_objects)
select
id,
dbo.cr_sample_fnPerRowRand()
from cte
where id <= 1000 -- limit the results to 1000 random numbers
尝试在RAND(seedInt)中使用种子值。RAND()每个语句仅执行一次,这就是为什么您每次看到的数字都相同的原因。
RIGHT(CONVERT(BIGINT, RAND(RecNo) * 1000000000000), 2)
:注意:我正在RIGHT
隐式地将BIGINT
to 转换为CHAR
,但要严格一点,您还要在其中添加另一个CONVERT
)。
如果您不需要整数,而是任何随机唯一标识符,则可以使用 newid()
SELECT table_name, newid() magic_number
FROM information_schema.tables
您需要为每一行调用RAND()。这是一个很好的例子
RAND()
一个视图,SELECT
将该视图的一个放入函数中,然后从任何地方调用该函数。聪明。
有时,与选定的“答案”有关的问题是分布并不总是均匀的。如果您需要在许多行之间非常均匀地分配随机数1-14,则可以执行以下操作(我的数据库有511个表,因此可以使用。如果行数少于随机数跨度,则不起作用好):
SELECT table_name, ntile(14) over(order by newId()) randomNumber
FROM information_schema.tables
从保持数字排序并使另一列随机化的意义上讲,这种做法与正常随机解决方案相反。
记住,我的数据库中有511个表(仅与我们从information_schema中选择的b / c有关)。如果我接受上一个查询并将其放入临时表#X中,然后对所得数据运行此查询:
select randomNumber, count(*) ct from #X
group by randomNumber
我得到了这个结果,向我表明我的随机数非常均匀地分布在许多行中:
DROP VIEW IF EXISTS vwGetNewNumber;
GO
Create View vwGetNewNumber
as
Select CAST(RAND(CHECKSUM(NEWID())) * 62 as INT) + 1 as NextID,
'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'as alpha_num;
---------------CTDE_GENERATE_PUBLIC_KEY -----------------
DROP FUNCTION IF EXISTS CTDE_GENERATE_PUBLIC_KEY;
GO
create function CTDE_GENERATE_PUBLIC_KEY()
RETURNS NVARCHAR(32)
AS
BEGIN
DECLARE @private_key NVARCHAR(32);
set @private_key = dbo.CTDE_GENERATE_32_BIT_KEY();
return @private_key;
END;
go
---------------CTDE_GENERATE_32_BIT_KEY -----------------
DROP FUNCTION IF EXISTS CTDE_GENERATE_32_BIT_KEY;
GO
CREATE function CTDE_GENERATE_32_BIT_KEY()
RETURNS NVARCHAR(32)
AS
BEGIN
DECLARE @public_key NVARCHAR(32);
DECLARE @alpha_num NVARCHAR(62);
DECLARE @start_index INT = 0;
DECLARE @i INT = 0;
select top 1 @alpha_num = alpha_num from vwGetNewNumber;
WHILE @i < 32
BEGIN
select top 1 @start_index = NextID from vwGetNewNumber;
set @public_key = concat (substring(@alpha_num,@start_index,1),@public_key);
set @i = @i + 1;
END;
return @public_key;
END;
select dbo.CTDE_GENERATE_PUBLIC_KEY() public_key;