2008-09-18 65 views
21

我在SQL Server 2005上運行SQL查詢,除了從數據庫查詢2列以外,還想隨機返回1列隨機數。我嘗試這樣做:如何作爲SQL Server 2005中的列返回隨機數字?

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

這有點兒工作,但問題是,這個查詢返回的每一行上相同的隨機數。每次運行查詢時都是一個不同的數字,但每行不一樣。我怎樣才能做到這一點,併爲每一行獲得一個新的隨機數字?

+0

看一看我的答案,你標記爲正確的答案是不正確的(你要求0到10000之間的數字)並且效率低下。 – 2009-01-29 22:14:41

+0

所以......你們否決了這個問題,因爲你不喜歡我選擇的答案? – 2009-01-30 15:10:57

+0

我已經接受了你的回答,因爲它客觀上更好(儘管亞當也做了我所需要的)。但是,我想強調的是,不應該根據所附答案對問題進行表決(或向上)。請根據問題的優點進行投票。 – 2009-01-30 15:16:04

回答

40

我意識到這是一個較舊的帖子......但你不需要一個視圖。

select column1, column2, 
    ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 10000 as column3 
from table1 
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借3210

1

對於SQLServer,有幾個選項。
1.一種while循環在時間來更新與一個隨機數空柱
2. .NET程序集包含返回一個隨機數

1

查詢函數

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

你可能想考慮生成UUID而不是使用NEWID函數的隨機數。這些保證在每次生成時都是唯一的,但是有一個很大的可能性,即一個簡單的隨機數會發生一些重複(並且取決於您使用它的可能會給您一個在稍後時刻調試錯誤的難題)

1

newid()我相信是非常耗費資源的。我記得在一張數百萬記錄的表格上嘗試這種方法,並且性能幾乎不如rand()。

4

警告

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的值永遠。當您生成1到10000之間的隨機數時,這可能不是什麼大問題,但1和5之間的相同算法會顯而易見。加1到你的mod。

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 
3
select RAND(CHECKSUM(NEWID())) 
1

我使用C#來處理隨機數。它更乾淨。我有一個函數用於返回一個隨機數和一個唯一鍵的列表,然後我只是在行號上加入uniqueKey。因爲我使用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 
相關問題