Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 Site Related Forums
 Article Discussion
 Article: Returning Rows in Random Order - Part II - Revenge of the Randomizer

Author  Topic 

AskSQLTeam
Ask SQLTeam Question

0 Posts

Posted - 2000-09-01 : 17:25:23
Wow, it looks like the Returning Rows in Random Order article is one of our most popular ever!

If you liked the first article, then read on; I received a number of very good follow up questions from Nick that you might find interesting. This article focuses on the performance of the solution I proposed in the first article, as well as the problems associated with returning a single randomly chosen row from a table.

Article Link.

rdwilliamsjr
Starting Member

4 Posts

Posted - 2001-12-19 : 10:17:56
-- Try this code to generate a random number
--
-- Calculate seed value
-- The seed is based on a GUID created by the NEWID function.
--
SELECT @seed = CONVERT(int, CONVERT(varbinary, REPLACE(CONVERT(varchar(50), NEWID()), '-', '')))

--
-- Use seed value in RAND() function to create a random number between specified minimum and maximum range.
--
SELECT @random_number = CONVERT(int, (1 + (@max_range - @min_range + 1) * RAND(@seed)))



Go to Top of Page

Robbo
Starting Member

1 Post

Posted - 2003-03-27 : 13:06:45
Try this - it uses the mod operator (%) based on number of milliseconds. Bit messy - but I've got some more testing before it's pukka.


SELECT CAST((rand(24701) * id) * 24701 AS int) % DATEPART(ms, GetDate() ) + DATEPART(ms, GetDate() ) AS random_order

Change to SELECT TOP 1 for single row.

I add the id of the row, but perhaps this isn't necessary?

The 24701 comes from the calling code and was genearted by another Random function which works a bit better than the sql Fn. Seems to work without this changing - but best to be safe...

- Robbo
zafos.com (one day I will finish my own website!)

Go to Top of Page

asiemer
Starting Member

1 Post

Posted - 2003-05-21 : 11:51:21
I use variations of this stored proc pretty much daily for paging through records. It is as fast as can be and very easy to work with. The ASP that you will need to use it is posted below.


CREATE PROCEDURE sp_PagedItems
(
@Page int,
@RecsPerPage int
)
AS

-- We don't want to return the # of rows inserted
-- into our temporary table, so turn NOCOUNT ON
SET NOCOUNT ON


--Create a temporary table
CREATE TABLE #TempItems
(
ID int IDENTITY,
Name varchar(50),
Price currency
)


-- Insert the rows from tblItems into the temp. table
INSERT INTO #TempItems (Name, Price)
SELECT Name,Price FROM tblItem ORDER BY Price

-- Find out the first and last record we want
DECLARE @FirstRec int, @LastRec int
SELECT @FirstRec = (@Page - 1) * @RecsPerPage
SELECT @LastRec = (@Page * @RecsPerPage + 1)

-- Now, return the set of paged records, plus, an indiciation of we
-- have more records or not!
SELECT *,
MoreRecords =
(
SELECT COUNT(*)
FROM #TempItems TI
WHERE TI.ID >= @LastRec
)
FROM #TempItems
WHERE ID > @FirstRec AND ID < @LastRec


-- Turn NOCOUNT back OFF
SET NOCOUNT OFF




-------------------------
-- And here is the ASP --
-------------------------



 
<!-- This assumes you already have a recordset object
explicitly created name objRS -->

<%
'How many records per page do we want to show?
Const iRecordsPerPage = 10

Dim currentPage 'what page are we on??
Dim bolLastPage 'are we on the last page?

if len(Request.QueryString("page")) = 0 then
currentPage = 1
else
currentPage = CInt(Request.QueryString("page"))
end if

'Show the paged results
strSQL = "sp_PagedItems " & currentPage & "," & iRecordsPerPage
objRS.Open strSQL, objConn

'See if we're on the last page
if Not objRS.EOF then
if CInt(objRS("MoreRecords")) > 0 then
bolLastPage = False
else
bolLastPage = True
end if
end if
%>
<P>

<TABLE BORDER=0 CELLSPACING=1 CELLPADDING=4 ALIGN=CENTER>
<TR><TH COLSPAN=2 BGCOLOR=NAVY>
<FONT SIZE=+1 COLOR=WHITE>
List of Items
</FONT>
</TH></TR>
<%
Do While Not objRS.EOF %>
<TR><TD ALIGN=LEFT BGCOLOR=GRAY>
<%=objRS("Name")%>
</TD><TD ALIGN=CENTER BGCOLOR=GRAY>
<%=FormatCurrency(objRS("Price"))%>
</TD></TR>
<% objRS.MoveNext
Loop %>
</TABLE>
<P>
<CENTER>
<%
'Only show the previous button if we are NOT on the first page
if currentPage > 1 then %>
<INPUT TYPE=BUTTON VALUE="<< Previous <%=iMaxRecords%> Records"
ONCLICK="document.location.href='thispage.asp?page=<%=currentPage-1%>'">
     
<% end if

'Only show the next button if we are NOT on the last page
if Not bolLastPage then %>
<INPUT TYPE=BUTTON VALUE="Next <%=iMaxRecords%> Records >>"
ONCLICK="document.location.href='thispage.asp?page=<%=currentPage+1%>'">
<% end if %>
</CENTER>


<div align="center">Andrew Siemer
asiemer@hotmail.com | www.drewsweb.com
.:: Changing the world one keystroke at a time ::.</div>
Go to Top of Page

Channing_Jones
Starting Member

2 Posts

Posted - 2003-12-09 : 12:03:31
You can also use the Sine-function to generate a nearly-random sequence:

"select top 10 * from myTable order by Sin(UnitID * Rand() * 1000)"

With UnitID being a unique value for each record. The 1000 ensures that the numbers are not within the same 2pi-period.
This will also work for older versions of sql-server.

Channing Jones
Go to Top of Page
   

- Advertisement -