21

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

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

哪种方法可行,但问题是此查询在每一行都返回相同的随机数。每次运行查询时它都是一个不同的数字,但它不会因行而异。我怎样才能做到这一点并为每一行获取一个新的随机数?

4

12 回答 12

41

我意识到这是一篇较旧的帖子......但你不需要视图。

select column1, column2, 
  ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 10000 as column3 
from table1
于 2009-01-29T12:55:45.243 回答
4

警告

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

相反,您可以使用这个答案

证明:

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 
于 2009-01-29T22:13:15.663 回答
3

亚当的回答非常有效,所以我将其标记为已接受。不过,当我在等待答案时,我还发现这个博客条目还有其他一些(随机性稍低)的方法。Kaboing的方法就是其中之一。

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

于 2008-09-18T18:23:47.120 回答
3
select RAND(CHECKSUM(NEWID()))
于 2010-12-07T03:00:56.787 回答
1

您需要使用 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 博客

于 2008-09-18T17:54:38.627 回答
1

对于 SQLServer,有几个选项。
1. 一次使用一个随机数更新空列的 while 循环
2. 包含返回随机数的函数的 .net 程序集

于 2008-09-18T17:58:10.943 回答
1

询问

select column1, column2, cast(new_id() as varchar(10)) as column3 
from table1
于 2008-09-18T17:58:20.177 回答
1

您可能想考虑使用 newid 函数生成 UUID 而不是随机数。这些保证每次生成时都是唯一的,而直接随机数很可能会发生一些重复(并且取决于您使用它的目的,可能会在以后给您带来非常难以调试的错误)

于 2008-09-18T18:42:05.330 回答
1

newid() 我认为是非常耗费资源的。我记得在有几百万条记录的表上尝试过这种方法,但性能不如 rand()。

于 2008-09-18T19:44:18.533 回答
1

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

于 2009-08-03T14:45:09.320 回答
1

这个片段似乎提供了一个合理的替代rand(),因为它返回一个介于 0.0 和 1.0 之间的浮点数。它仅使用由提供的最后 3 个字节,因此总随机性可能与从推荐答案转换为然后进行修改newid()略有不同。没有机会测试相对性能,但对于我的目的来说似乎足够快(并且足够随机)。VARBINARYINT

SELECT CAST(SubString(CONVERT(binary(16), newid()), 14, 3) AS INT) / 16777216.0 AS R
于 2009-11-13T20:03:58.877 回答
1

我使用 c# 来处理随机数。干净多了。我有一个函数用于返回随机数列表和唯一键,然后我只需在行号上加入唯一键。因为我使用 c#,所以我可以轻松地指定随机数必须落在的范围。

以下是制作函数的步骤: http ://www.sqlwithcindy.com/2013/04/elegant-random-number-list-in-sql-server.html

这是我的查询最终的样子:

SELECT 
   rowNumber, 
   name, 
   randomNumber
FROM dbo.tvfRandomNumberList(1,10,100) 
INNER JOIN (select ROW_NUMBER() over (order by int_id) as 'rowNumber', name from client        
            )as clients
ON clients.rowNumber = uniqueKey
于 2013-04-25T21:41:13.683 回答