如何在 SQL Server 2005 中将随机数作为列返回?
Posted
技术标签:
【中文标题】如何在 SQL Server 2005 中将随机数作为列返回?【英文标题】:How do I return random numbers as a column in SQL Server 2005? 【发布时间】:2010-09-10 19:53:48 【问题描述】:我在 SQL Server 2005 上运行 SQL 查询,除了从数据库中查询 2 列之外,我还想返回 1 列随机数以及它们。我试过这个:
select column1, column2, floor(rand() * 10000) as column3
from table1
哪种方法可行,但问题是该查询在每一行都返回相同的随机数。每次运行查询时它都是一个不同的数字,但它不会因行而异。我怎样才能做到这一点并为每一行获取一个新的随机数?
【问题讨论】:
看看我的答案,你标记为正确的答案是不正确的(你问的是0到10000之间的数字)而且效率低下。 所以...您否决了这个问题,因为您不喜欢我选择的答案? 我接受了你的回答,因为客观上它更好(尽管亚当也做了我需要的)。但是,我想强调的是,不应根据附加的答案对问题进行否决(或否决)。请根据问题的优劣投票。 见:***.com/questions/493739/… 我给了你一个 +1,因为现在它是正确的,请注意正确的答案是蒂莫西斯,我没有得分...... 【参考方案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's SQL Server Blog
【讨论】:
【参考方案2】:对于 SQLServer,有几个选项。 1. 一次使用一个随机数更新空列的 while 循环 2. .net 程序集,包含一个返回随机数的函数
【讨论】:
【参考方案3】:查询
select column1, column2, cast(new_id() as varchar(10)) as column3
from table1
【讨论】:
【参考方案4】:Adam 的回答效果很好,所以我将其标记为已接受。不过,当我在等待答案时,我还发现这个博客条目还有其他一些(随机性稍低)的方法。 Kaboing 的方法就是其中之一。
http://blog.sqlauthority.com/2007/04/29/sql-server-random-number-generator-script-sql-query/
【讨论】:
【参考方案5】:您可能想考虑使用 newid 函数生成 UUID 而不是随机数。每次生成这些都保证是唯一的,而直接随机数很可能会发生一些重复(并且取决于您使用它的目的,可能会在以后给您带来非常难以调试的错误)
【讨论】:
【参考方案6】:newid() 我认为是非常耗费资源的。我记得在有几百万条记录的表上尝试过这种方法,但性能不如 rand()。
【讨论】:
【参考方案7】:我知道这是一篇较旧的帖子...但您不需要查看。
select column1, column2,
ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 10000 as column3
from table1
【讨论】:
你要不要回答这个问题,我会删除我的并将mod添加到你的 我也可以给这个+1 :) 这个问题/答案也可能很有价值:上述的较短版本:***.com/a/9039661/47226【参考方案8】:警告
Adam's answer 涉及视图的效率非常低,并且对于非常大的集合可能会占用您的数据库很长时间,我强烈建议您不要定期使用它,或者在您需要在生产中填充大型表的情况下使用它.
您可以改为使用this answer。
证明:
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)
分析器跟踪:
alt text 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
【讨论】:
每种情况下的数字有多随机? 我会确认,对于 1 到 10000 之间的数字,请坚持住 扩展答案,证明东西是随机的【参考方案9】:根据我的测试,上面的答案永远不会产生 10000 的值。当您生成 1 到 10000 之间的随机数时,这可能不是什么大问题,但是 1 到 5 之间的相同算法会很明显。将 1 添加到您的模组中。
【讨论】:
问题不在于生成特定范围内的随机数。任何随机数都可以。 10000 只是我在代码示例中使用的任意数字。【参考方案10】:这个 sn-p 似乎为rand()
提供了一个合理的替代品,因为它返回一个介于 0.0 和 1.0 之间的浮点数。它仅使用newid()
提供的最后 3 个字节,因此总随机性可能与转换为VARBINARY
然后INT
然后从推荐的答案进行修改略有不同。没有机会测试相对性能,但对于我的目的来说似乎足够快(并且足够随机)。
SELECT CAST(SubString(CONVERT(binary(16), newid()), 14, 3) AS INT) / 16777216.0 AS R
【讨论】:
【参考方案11】:select RAND(CHECKSUM(NEWID()))
【讨论】:
这确实有效。你明白我的意思。简单直接回答问题。谢谢!【参考方案12】:我使用 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
【讨论】:
以上是关于如何在 SQL Server 2005 中将随机数作为列返回?的主要内容,如果未能解决你的问题,请参考以下文章
在 SQL Server 2005 中将不安全的程序集部署到生产环境
在 SQL Server 2005 中将列标识上的标识设置为另一个表的列
如何在 SQL Server 中将纪元时间与 24 小时前进行比较?