Ok, this isn't the most elegant solution, but is is a proper "Simple Random Sample" and is very fast
/*
FAST Simple Random Sample from a source table using pseudo random number generator RAND()
Usage:
Sample Size is set following the "select top"
Copy and paste more random value subqueries than the sample size
If the sample size is more than 20% of the source table size, you may have to include many time the sample size of random value subqueries
and if more than 50%, consider changing the query to exlude the random rows.
Modify the @SourceRowCount and the first part of the query for your source table name (dbo.phrases in this example)
A random seed is used, but a fixed one can be used if desired
Advantages:
Does not use NEWID for randomness, which is not technically a Random Number Genrator
Is FAST, even when the source table is large Select 10 from 10 million in 6 seconds, 1000 in 8 seconds
Does not rely on data page assumptions (see TABLESAMPLE)
Disadvantages:
Not TRUE random numbers
See Also:
http://msdn.microsoft.com/en-us/library/aa175776(SQL.80).aspx
Presents three methods for random samples
1) Cursors and RAND() Cursor Overhead
2) Rand( ROW ID) Bad randomness
3) NewID
http://msdn.microsoft.com/en-us/library/ms189108.aspx
Documentation for TABLESAMPLE
1) Can only be used on true tables, not linked, views, XML, etc
2) Samples pages, not rows, if pages contain correlated row its no longer a simple random sample
*/
/*
Find the number of rows in the source table
*/
declare @SourceRowCount integer
select @SourceRowCount=COUNT(*) from dbo.phrases
/*
Initialize the random number generator with a random seed (or a particular seed)
*/
declare @d integer
set @d=RAND() --set @d=RAND(an integer)
/*
Create Source table from the desired table and ROW_NUMBER()
Join Source to a table of random values between
Select top n from a slightly larger set
*/
select * from
(select *, ROW_NUMBER() over(order by GETDATE()) as Row from dbo.phrases)
as source,
(select top 10 n from
(select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n union all
select convert(integer, RAND()*@SourceRowCount) as n)
as tmp)
as R where source.Row=R.n