可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm running a SQL query on SQL Server 2005, and in addition to 2 columns being queried from the database, I'd also like to return 1 column of random numbers along with them. I tried this:
select column1, column2, floor(rand() * 10000) as column3
from table1
Which kinda works, but the problem is that this query returns the same random number on every row. It's a different number each time you run the query, but it doesn't vary from row to row. How can I do this and get a new random number for each row?
回答1:
I realize this is an older post... but you don't need a view.
select column1, column2,
ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 10000 as column3
from table1
回答2:
WARNING
Adam's answer involving the view is very inefficient and for very large sets can take out your database for quite a while, I would strongly recommend against using it on a regular basis or in situations where you need to populate large tables in production.
Instead you could use this answer.
Proof:
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)
Profiler trace:
alt text http://img519.imageshack.us/img519/8425/destroydbxu9.png
This is proof that stuff is random enough for numbers between 0 to 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
回答3:
Adam's answer works really well, so I marked it as accepted. While I was waiting for an answer though, I also found this blog entry with a few other (slightly less random) methods. Kaboing's method was among them.
http://blog.sqlauthority.com/2007/04/29/sql-server-random-number-generator-script-sql-query/
回答4:
select RAND(CHECKSUM(NEWID()))
回答5:
You need to use a UDF
first:
CREATE VIEW vRandNumber
AS
SELECT RAND() as RandNumber
second:
CREATE FUNCTION RandNumber()
RETURNS float
AS
BEGIN
RETURN (SELECT RandNumber FROM vRandNumber)
END
test:
SELECT dbo.RandNumber(), *
FROM <table>
Above borrowed from Jeff's SQL Server Blog
回答6:
For SQLServer, there are a couple of options.
1. A while loop to update an empty column with one random number at a time
2. A .net Assembly that contains a function that returns a random number
回答7:
You might like to consider generating a UUID instead of a random number using the newid function. These are guaranteed to be unique each time generated whereas there is a significant chance that some duplication will occur with a straightforward random number (and depending on what you're using it for could give you a phenominally hard to debug error at a later point)
回答8:
newid() i believe is very resource intensive. i recall trying that method on a table of a few million records and the performance wasn't nearly as good as rand().
回答9:
According to my testing, the answer above doesn't generate a value of 10000 ever. This probably isn't much of a problem when you are generating a random between 1 and 10000, but the same algorithm between 1 and 5 would be noticable. Add 1 to your mod.
回答10:
This snippet seems to provide a reasonable substitute for rand()
in that it returns a float between 0.0 and 1.0. It uses only the last 3 bytes provided by newid()
so total randomness may be slightly different than the conversion to VARBINARY
then INT
then modding from the recommended answer. Have not had a chance to test relative performance but seems fast enough (and random enough) for my purposes.
SELECT CAST(SubString(CONVERT(binary(16), newid()), 14, 3) AS INT) / 16777216.0 AS R
回答11:
I use c# for dealing with random numbers. It's much cleaner. I have a function I use to return a list of random number and a unique key, then I just join the uniqueKey on the row number. Because I use c#, I can easily specify a range within which the random numbers must fall.
Here are the steps to making the function:
http://www.sqlwithcindy.com/2013/04/elegant-random-number-list-in-sql-server.html
Here is what my query ends up looking like:
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
回答12:
Query
select column1, column2, cast(new_id() as varchar(10)) as column3
from table1