我如何生成一个随机数为每一行在T-SQL选择?

表中的每一行都需要一个不同的随机数。下面的代码对每一行使用相同的随机值。

SELECT table_name, RAND() magic_number
FROM information_schema.tables

我想从中得到一个INT或FLOAT。接下来,我将使用这个随机数从已知日期创建一个随机日期偏移量,例如从开始日期的1-14天偏移量。

这是为Microsoft SQL Server 2000。

496126 次浏览

当在单个批处理中多次调用rand()时,将返回相同的数字。

我建议使用convert(varbinarynewid())作为种子参数:

SELECT table_name, 1.0 + floor(14 * RAND(convert(varbinary, newid()))) magic_number
FROM information_schema.tables

newid()保证每次调用都会返回不同的值,即使是在同一个批处理中,因此将它作为种子将提示rand()每次给出不同的值。

编辑以获得从1到14的随机整数。

看看SQL Server -设置基于随机数字,它有一个非常详细的解释。

综上所述,下面的代码生成了一个0到13之间的随机数,包括均匀分布:

ABS(CHECKSUM(NewId())) % 14

要更改范围,只需更改表达式末尾的数字。如果你需要一个同时包含正数和负数的范围,要格外小心。如果你做错了,可能会重复计算数字0。

给在座的数学狂人们一个小警告:这段代码中有一个非常轻微的偏差。CHECKSUM()的结果在整个sql Int数据类型范围内是统一的,或者至少像我的(编辑器)测试所显示的那样。但是,当CHECKSUM()在该范围的最顶端生成一个数字时,将会有一些偏差。任何时候,如果您在最大可能整数和所需范围大小的最后一个精确倍数(本例中为14)之间得到一个数字,那么这些结果将优先于范围的剩余部分,这些结果无法从14的最后一个倍数中产生。

例如,假设Int类型的整个范围只有19。19是最大的整数。当CHECKSUM()的结果为14-19时,这些结果对应于结果0-5。这些数字将更倾向于严重而不是6-13,因为CHECKSUM()生成它们的可能性是前者的两倍。更容易直观地演示这一点。下面是我们的虚整数范围的全部可能结果集:

Checksum Integer: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Range Result:     0 1 2 3 4 5 6 7 8 9 10 11 12 13  0  1  2  3  4  5

你可以在这里看到,产生某些数字的机会比产生其他数字的机会更多:偏见。值得庆幸的是,Int类型的实际范围是更大…在大多数情况下,这种偏差几乎是无法检测到的。但是,如果您发现自己正在为严肃的安全代码执行此操作,则需要注意这一点。

使用newid ()

select newid()

或者可能是这个

select binary_checksum(newid())

尝试在RAND中使用种子值(seedInt)。RAND()每条语句只执行一次,这就是为什么每次都看到相同的数字。

如果你不需要它是一个整数,而是任何随机的唯一标识符,你可以使用newid()

SELECT table_name, newid() magic_number
FROM information_schema.tables

您是否在每一行中都有一个整数值,可以作为种子传递给RAND函数?

要得到1到14之间的整数,我相信这是可行的:

FLOOR( RAND(<yourseed>) * 14) + 1

Rand()函数将生成相同的随机数,如果在表SELECT查询中使用。如果对Rand函数使用种子,同样适用。另一种方法是使用这个:

SELECT ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) AS [RandomNumber]

在这里得到的信息,它很好地解释了问题。

RAND(CHECKSUM(NEWID()))

上面将生成一个(伪)随机数,介于0和1之间,不排除。如果在选择中使用,因为种子值每一行都在变化,它将为每一行生成一个新的随机数(但不保证每一行生成一个唯一的数字)。

当与10的上限组合时(产生数字1 - 10):

CAST(RAND(CHECKSUM(NEWID())) * 10 as INT) + 1

transact - sql批量文档:

  1. CAST(): https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql
  2. RAND(): http://msdn.microsoft.com/en-us/library/ms177610.aspx
  3. CHECKSUM(): http://msdn.microsoft.com/en-us/library/ms189788.aspx
  4. NEWID(): https://learn.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql

我有时对所选“答案”的问题是,分布并不总是均匀的。如果您需要在大量行中随机分布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

我得到这个结果,显示我的随机数非常均匀地分布在许多行中:

enter image description here

如果你需要保存你的种子,以便它每次生成“相同”的随机数据,你可以做以下事情:

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()函数,然后在选择语句中使用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

生成1000到9999之间的随机数,包括:

FLOOR(RAND(CHECKSUM(NEWID()))*(9999-1000+1)+1000)

"+1" -包含上限值(上例为9999)

回答老问题,但是这个答案之前没有提供,希望这对通过搜索引擎找到这个结果的人有用。

在SQL Server 2008中,引入了一个新函数CRYPT_GEN_RANDOM(8),它使用CryptoAPI生成一个加密强随机数,返回为VARBINARY(8000)。下面是文档页面:https://learn.microsoft.com/en-us/sql/t-sql/functions/crypt-gen-random-transact-sql

因此,为了获得一个随机数,你可以简单地调用函数并将其强制转换为必要的类型:

select CAST(CRYPT_GEN_RANDOM(8) AS bigint)

或者要在-1和+1之间获得float,你可以这样做:

select CAST(CRYPT_GEN_RANDOM(8) AS bigint) % 1000000000 / 1000000000.0
select ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) as [Randomizer]

一直对我有效吗

select round(rand(checksum(newid()))*(10)+20,2)

这里的随机数在20和30之间。 round将给出两个小数点后的最大值

如果你想要负数,你可以这样做

select round(rand(checksum(newid()))*(10)-60,2)

那么最小值将是-60,最大值将是-50。

    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;

很简单:

DECLARE @rv FLOAT;
SELECT @rv = rand();

这将把一个0-99之间的随机数放入表中:

CREATE TABLE R
(
Number int
)


DECLARE @rv FLOAT;
SELECT @rv = rand();


INSERT INTO dbo.R
(Number)
values((@rv * 100));


SELECT * FROM R
Update my_table set my_field = CEILING((RAND(CAST(NEWID() AS varbinary)) * 10))

1到10之间的数字。

试试这个:

SELECT RAND(convert(varbinary, newid()))*(b-a)+a magic_number

其中a是较小的数字,而b是较大的数字

如果你想生成一个1到14之间的随机数。

SELECT CONVERT(int, RAND() * (14 - 1) + 1)

SELECT ABS(CHECKSUM(NewId())) % (14 -1) + 1

如果你需要一个特定的随机数你可以使用递归CTE:

;WITH A AS (
SELECT 1 X, RAND() R
UNION ALL
SELECT X + 1, RAND(R*100000) --Change the seed
FROM A
WHERE X < 1000 --How many random numbers you need
)
SELECT
X
, RAND_BETWEEN_1_AND_14 = FLOOR(R * 14 + 1)
FROM A
OPTION (MAXRECURSION 0) --If you need more than 100 numbers