I said:
Working from the tried & true SQL Server favorite...
[snip]
...My conclusion? Jimmy could get by with this:
Randomize()
Set oRS=oConn.Execute("SELECT TOP 1 EMAIL_ADDRESS FROM TABLE1
ORDER BY Rnd(-Rnd(ID*" & -Rnd & "))")
Just to put the final nail in this thread, I think it is fair to point out
that my analysis is thoroghly incomplete. I did no comparison between using
a column-based ordering and my solution, nor did I examine anything but a
simple example. My solution may be acceptible for a table with 9 records,
each with an identity under 10, but it made no attempt to do the same for a
larger table with sequence gaps and a wide range of identities.
To illustrate the danger of relying on limited analysis, I offer this
observation: When run against Northwind's [Orders] table (approximately 830
unique IDs), the distribution is horribly skewed toward a small handful of
values. Over a run of 10,000, I only hit about 700 values, with most in
single digits for frequency, but five values in excess of 100 -- one of
those values appearing 343 times!
Just to be sure this was not an aberration, I ran it again. These are the
top 10 values, ordered by frequency:
Run 1 Run 2
========= =========
10700 343 10700 355
10497 257 11005 224
11005 217 10497 223
10561 156 10561 167
10601 140 10601 133
10397 81 11016 85
11022 80 10397 83
11016 78 11022 82
11017 72 10843 66
10714 60 11017 66
Those are virtually the same values. Moreover, a flat distribution would
have yielded 830 values with roughly 12 appearances each. So my suggestion
is far from ideal for this data set.
There *is* a better way to get a random distribution. This one is as good as
your random number generator. Oddly enough, it turned in better performance
than my earlier suggestion. It is in JScript, so the distribution depends on
Math.random():
Step 1: Get a count
RS = CN.Execute("SELECT Count(*) AS RecordCount FROM Orders")
rc = RS.Fields("RecordCount").Value
Step 2: Use top 1 DESC from top N ASC to get your row
RS = CN.Execute("SELECT TOP 1 * FROM Orders WHERE OrderID IN (SELECT TOP
" + Math.ceil(rc*Math.random()) + " OrderID FROM Orders ORDER BY OrderID
ASC) ORDER BY OrderID DESC")
Run 50,000 times against [Orders], I got minimum frequency 35 and maximum
88. All 830 values were covered. Using VBScript and Rnd**, results were
similar, with frequencies ranging from 38 to 90.
I have no more to say on the topic. I think.
** What a pain in the posterior THAT was. It took me quite some time to
figure out that I needed to use CSng() on the recordcount to multiply
against Rnd without an overflow. Never mind that it took twice as many lines
of code. Who needs that nonsense?