如何在SQL Server 2005中将随机数作为列返回?

时间:2020-03-06 14:22:34  来源:igfitidea点击:

我正在SQL Server 2005上运行SQL查询,除了要从数据库中查询2列之外,我还想返回1列随机数和它们。我尝试了这个:

select column1, column2, floor(rand() * 10000) as column3 
from table1

哪种方法有效,但问题是此查询在每行上返回相同的随机数。每次我们运行查询时,它都是一个不同的数字,但每一行并没有变化。如何做到这一点,并为每行获取一个新的随机数?

解决方案

我们需要使用UDF

第一的:

CREATE VIEW vRandNumber
AS
SELECT RAND() as RandNumber

第二:

CREATE FUNCTION RandNumber()
RETURNS float
AS
  BEGIN
  RETURN (SELECT RandNumber FROM vRandNumber)
  END

测试:

SELECT dbo.RandNumber(), *
FROM <table>

以上是从Jeff的SQL Server博客借来的

对于SQLServer,有两个选项。

  1. while循环,一次用一个随机数更新一个空列
    2.一个.net程序集,其中包含一个返回随机数的函数

询问

select column1, column2, cast(new_id() as varchar(10)) as column3 
from table1

亚当的答案非常有效,因此我将其标记为已接受。在等待答案的同时,我还发现了此博客条目以及其他一些方法(随机性略低)。 Kaboing的方法就是其中之一。

http://blog.sqlauthority.com/2007/04/29/sql-server-random-number-generator-script-sql-query/

我们可能要考虑使用newid函数生成UUID而不是随机数。保证每次生成时它们都是唯一的,而很有可能以直接的随机数进行某些重复(并且根据我们使用的目的,这可能会在以后给我们带来明显的调试困难)

我相信newid()占用大量资源。我记得在几百万条记录的表上尝试这种方法,其性能几乎不如rand()好。

我知道这是一篇较旧的文章...但是我们不需要查看。

select column1, column2, 
  ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 10000 as column3 
from table1

警告

Adam涉及该视图的答案非常低效,并且对于非常大的集合可能会占用我们一段时间的数据库,因此强烈建议我们不要定期使用它,或者在需要在生产中填充大表的情况下使用它。

相反,我们可以使用此答案。

证明:

CREATE VIEW vRandNumber
AS
SELECT RAND() as RandNumber

go 

CREATE FUNCTION RandNumber()
RETURNS float
AS
  BEGIN
  RETURN (SELECT RandNumber FROM vRandNumber)
  END

go 

create table bigtable(i int)

go 

insert into bigtable 
select top 100000 1 from sysobjects  a
join sysobjects b on 1=1

go 

select cast(dbo.RandNumber() * 10000 as integer) as r into #t from bigtable 
-- CPU (1607) READS (204639) DURATION (1551)

go

select ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 10000 as r  into #t1 
from bigtable
-- Runs 15 times faster - CPU (78) READS (809) DURATION (99)

探查器跟踪:

替代文字http://img519.imageshack.us/img519/8425/destroydbxu9.png

这证明东西对于0到9999之间的数字是足够随机的

-- proof that stuff is random enough 
select avg(r) from #t
-- 5004
select STDEV(r) from #t
-- 2895.1999 

select avg(r) from #t1
-- 4992
select STDEV(r) from #t1
-- 2881.44 

select r,count(r) from #t
group by r 
-- 10000 rows returned 

select r,count(r) from #t1
group by r 
-- 10000 row returned

根据我的测试,上面的答案永远不会产生10000的值。当我们生成1到10000之间的随机数时,这可能不是什么大问题,但是在1到5之间的相同算法很明显。将1加到模组中。

该代码段似乎可以合理地替代rand(),因为它返回的浮点数介于0.0和1.0之间。它仅使用newid()提供的最后3个字节,因此总随机性可能与转换为VARBINARY然后是INT然后从建议的答案转换的方式略有不同。尚未有机会测试相对性能,但就我的目的而言似乎足够快(足够随机)。

SELECT CAST(SubString(CONVERT(binary(16), newid()), 14, 3) AS INT) / 16777216.0 AS R

select RAND(CHECKSUM(NEWID()))