2014-10-27 100 views
0

我有一個表有超過100萬條記錄,我想從表中選擇隨機行,但不是在所有記錄中 - 只從符合特定條件的結果中選擇隨機行。MSSQL選擇在大數據中隨機

性能是很重要,所以我不能使用NEWID排序,然後選擇第一項。

表結構是一些這樣的事:

ID BIGINT 
Title NVARCHAR(100) 
Level INT 
Point INT 

現在,我寫了一個查詢,如:

with 
    tmp_one as 
    (
     SELECT 
       R.Id as RID 
       FROM [User] as U 
          Inner Join 
         [Item] as R 
          On R.UserId = U.Id 

       WHERE  ([R].[Level] BETWEEN @MinLevel AND @MaxLevel) 
         AND ((ABS((BINARY_CHECKSUM(NEWID(),R.Id,NEWID())))% 10000)/100) > @RangeOne 
    ), 
    tmp_two as 
    (
     Select tmp_one.RID as RID 
      From tmp_one 
      Where ((ABS((BINARY_CHECKSUM(NEWID(),RID,NEWID())))% 10000)/100) > @RangeTwo 
    ), 
    tmp_three as 
    (
     Select RID as RID 
      From tmp_two 
      Where ((ABS((BINARY_CHECKSUM(NEWID(),NEWID())))% 10000)/100) < @RangeThree 
    ) 
    Select top 10 RID 
     From tmp_three 

我想選擇10項隨機,然後選擇其中的一個,但我有一個驚人的問題!

有時輸出按物品等級排序!我不想要它(它不是真的隨機)。我真的不知道結果是按等級排序的。

請建議一些解決方案,幫助我選擇高性能隨機記錄和隨機選擇的高迭代範圍內不重複。

+3

你有沒有ORDER BY TOP。所以你告訴SQL Server「我不關心訂單!」因此,SQL Server按照它認爲最有效的順序將數據返回給您。 – 2014-10-27 20:30:58

+0

okey,我怎樣才能防止這種有效的順序,並告訴只使用默認的順序,不要改變它? (插入順序) 以及爲什麼這不會發生在常規選擇和選擇顯示數據插入順序? – Behrooz 2014-10-27 20:41:16

+1

請點擊這裏閱讀#3:[SQL Server Assumptions](http://blogs.sqlsentry.com/aaronbertrand/t-sql-tuesday-56-sql-server-assumptions/) – 2014-10-27 20:52:55

回答

-1

嘗試類似這樣的事情。它會隨機抓取你桌子上的10行。

這是僞代碼,所以您可能需要修復幾個列名以匹配您的真實表。

DECLARE @Random int 
DECLARE @Result table 
(ID BIGINT, 
Title varchar(100), 
Level int, 
Point int) 

declare @TotalRows int 
set @TotalRows = (select COUNT(*) From [User] U inner join [Item] R on R.UserID = U.ID) 

while (select COUNT(*) from @Result)<10 
begin 
set @Random = (select floor(RAND() * @TotalRows+1)) 

insert into @Result 
select T1.ID, T1.Title, T1.Level, T1.Point from 
(select top (@Random) * From [User] U inner join [Item] R on R.UserID = U.ID) T1 
left outer join (select top (@Random) * From [User] U inner join [Item] R on R.UserID = U.ID) T2 on T2.ID = T1.ID 
where T2.ID is null 


end 

select * from @Result 

這是它是如何工作的。

Select a random number. For example 47. 
We want to select the 47th row of the table. 
Select the top 47 rows, call it T1. 
Join it to the top 46 rows called T2. 
The row where T2 is null is the 47th row. 
Insert that into a temporary table. 
Do it until there are 10 rows. 
Done. 
1

從MSDN的Selecting Rows Randomly from a Large Table基礎,而不是一個你避免:

select top 10 * from TableName order by newid() 

這表明這一點:

select top 10 * from TableName where (abs(cast((binary_checksum(*) * rand()) as int)) % 100) < 10 

它只是非常小的邏輯讀取更好的性能。