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
 SQL Server 2000 Forums
 SQL Server Development (2000)
 Aarrgh! Paging through sorted data...

Author  Topic 

Daze
Starting Member

42 Posts

Posted - 2008-05-27 : 16:06:04
I'm trying to write a stored procedue that will return a page of sorted data. I've seen numerous posts here (and via Google), but I've yet to find a solution that works.

Basically, I'm an ASP.Net (C#) developer. I'm working on a page that contains a GridView, and I need to supply the GridView control with the appropriate page of data. I also need to be able to sort the data (by clicking on the column headers). This presents me with one major problem:

I need to create a stored procedure that can sort on any column, with switchable sort directions, (all of this information is available from the GridView control) and return only a page of the sorted data. E.g. Each time the user clicks on a column heading in the GridView, I need to sort the entire data and return a single page of sorted data. I want to do this server side, rather than returning all of the data and then sorting and paging it.

What is the best way of achieving this in SQL 2000?

Do I need to populate a table variable, sort it and then grab a page of data, or is there a more efficient way? I assume that, because of the need to sort on any column, dynamic SQL generation is the only way forward?

This is all relatively straight forward without the need to sort on any column. Greg Hamilton's solution works great until you introduce the need to sort the data.

Thanks in advance for any help.

Daze.

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2008-05-27 : 16:10:17
Just use a dynamic ORDER BY in combination with whatever paging solution you choose.

Make sure to check out the comments of this article as it shows how to deal with the different data types and sort directions:
http://www.sqlteam.com/article/dynamic-order-by

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Database maintenance routines:
http://weblogs.sqlteam.com/tarad/archive/2004/07/02/1705.aspx
Go to Top of Page

Daze
Starting Member

42 Posts

Posted - 2008-05-27 : 16:20:00
Hi tkizer. Thanks for taking the time to reply.

But how do I determine where the page of data is that I need? I need to have a handle to each row of data so that I can determine which collection of records make up my page of data.

For example: If I sort on (say) the CompanyName, the CompanyId (INT, PK) will be out of sequence, so I can't use CompanyId to determine where the page starts, and where the page of data ends.

I need to sort the data before I page it - I don't want to just sort a page of data.

...or am I missing something?

This is the paging code without any sorting logic. As it uses CompanyId to locate records, it won't work if I sort on any other field.

CREATE  PROCEDURE [dbo].[LoadPagedCompanies] 
(
@startRowIndex int,
@maximumRows int
)
AS

DECLARE @first_id int

SET ROWCOUNT @startRowIndex
SELECT @first_id = CompanyId FROM Company ORDER BY CompanyId

SET ROWCOUNT @maximumRows

SELECT c.*
FROM Company c
WHERE CompanyId >= @first_id
ORDER BY c.CompanyId

SET ROWCOUNT 0

GO


Daze.
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2008-05-27 : 16:25:26
The solution that we use in SQL Server 2000 uses temp tables with an identity column. You insert the entire record set into the temp table in the order you want it. You then grab your page of data by filtering on the identity column.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Database maintenance routines:
http://weblogs.sqlteam.com/tarad/archive/2004/07/02/1705.aspx
Go to Top of Page

Daze
Starting Member

42 Posts

Posted - 2008-05-27 : 17:31:51
Thanks again tkizer.

Can you point me in the direction of any sample code? How are you inserting the data into the temp table in the correct order?



Daze.
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2008-05-27 : 17:46:19
You provide the dynamic ORDER BY in your insert into the temp table.

Here is an example from one of our stored procedures. I've modified it to hide proprietary stuff, so my actual procedure is more complex and uses different column names, table names, parameter names, etc...


CREATE PROCEDURE [dbo].[SomeProc]
(@parm1 int,@Page int = 1,@RecsPerPage float = 200
,@sortOn varchar(25) = 'assetID'
,@sortDirection varchar(15) = 'DESC')

AS

SET NOCOUNT ON

CREATE TABLE #TempItems (ID int IDENTITY, assetID int)

Insert Into #TempItems (assetID)
SELECT assetID
FROM SomeTable
WHERE SomeColumn = @parm1
ORDER BY
CASE --Varchar
WHEN @sortOn = 'assetID' AND @sortDirection = 'DESC' THEN assetID
WHEN @sortOn = 'Column2' AND @sortDirection = 'DESC' THEN Column2
ELSE Null
END DESC,

CASE
WHEN @sortOn = 'assetID' AND @sortDirection = 'ASC' THEN assetID
WHEN @sortOn = 'Column2' AND @sortDirection = 'ASC' THEN Column2
ELSE Null
END ASC,

CASE --date
WHEN @sortOn = 'Column3' AND @sortDirection = 'DESC' THEN Column3
ELSE Null
END DESC,

CASE
WHEN @sortOn = 'Column3' AND @sortDirection = 'ASC' THEN Column3
ELSE Null
END ASC,

CASE --INT
WHEN @sortOn = 'Column4' AND @sortDirection = 'DESC' THEN Column4
ELSE Null
END DESC,

CASE
WHEN @sortOn = 'Column4' AND @sortDirection = 'ASC' THEN Column4
ELSE Null
END ASC

DECLARE @FirstRec int, @LastRec int, @TotalPages int, @totalRecords int

SELECT @FirstRec = (@Page - 1) * @RecsPerPage
SELECT @LastRec = (@Page * @RecsPerPage + 1)
Declare @Hours float

select @totalRecords = (Select count (distinct assetID)) from #TempItems

Select
@totalRecords as totalRecords,
AssetID,
FROM
#TempItems TempTable
Where (ID > @FirstRec AND ID < @LastRec)
Order By ID ASC




Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Database maintenance routines:
http://weblogs.sqlteam.com/tarad/archive/2004/07/02/1705.aspx
Go to Top of Page

Daze
Starting Member

42 Posts

Posted - 2008-05-27 : 17:58:09
Thanks again.

I'd read somewhere that the INSERT statement wouldn't necessarily "honour" the ORDER BY, and that the resulting data could be out of sequence?!

I'll give this a go.

Cheers

Daze.
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2008-05-27 : 18:24:37
An ORDER BY is always honored. We are guaranteed the paging order since we are using an identity column and an ORDER BY in the INSERT/SELECT.

You are probably referring to retrieving the data from a table though. If you were to just SELECT * FROM #TempItems, we aren't guaranteed anything. Once you add an ORDER BY though, we are guaranteed which order it'll be returned.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Database maintenance routines:
http://weblogs.sqlteam.com/tarad/archive/2004/07/02/1705.aspx
Go to Top of Page

pootle_flump

1064 Posts

Posted - 2008-05-28 : 05:11:48
The order by clause is logically honoured in so far as the identity column values will logically match the order by clause. However, the physical order of data written to pages will not necessarily match the order by clause - the engine will simply write these optimally. This might be what you are referring to - as such it is not something that affects this application.
Go to Top of Page

Daze
Starting Member

42 Posts

Posted - 2008-05-28 : 17:17:14
Thanks all - I got this working earlier today. I also tweaked it slightly by adding the SET ROWCOUNT optimisation.

Daze.
Go to Top of Page
   

- Advertisement -