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-byTara KizerMicrosoft MVP for Windows Server System - SQL Serverhttp://weblogs.sqlteam.com/tarad/Database maintenance routines:http://weblogs.sqlteam.com/tarad/archive/2004/07/02/1705.aspx |
 |
|
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)ASDECLARE @first_id intSET ROWCOUNT @startRowIndexSELECT @first_id = CompanyId FROM Company ORDER BY CompanyIdSET ROWCOUNT @maximumRowsSELECT c.*FROM Company cWHERE CompanyId >= @first_idORDER BY c.CompanyIdSET ROWCOUNT 0GO Daze. |
 |
|
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 KizerMicrosoft MVP for Windows Server System - SQL Serverhttp://weblogs.sqlteam.com/tarad/Database maintenance routines:http://weblogs.sqlteam.com/tarad/archive/2004/07/02/1705.aspx |
 |
|
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. |
 |
|
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 ONCREATE TABLE #TempItems (ID int IDENTITY, assetID int)Insert Into #TempItems (assetID)SELECT assetID FROM SomeTableWHERE 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 ASCDECLARE @FirstRec int, @LastRec int, @TotalPages int, @totalRecords int SELECT @FirstRec = (@Page - 1) * @RecsPerPageSELECT @LastRec = (@Page * @RecsPerPage + 1)Declare @Hours floatselect @totalRecords = (Select count (distinct assetID)) from #TempItemsSelect @totalRecords as totalRecords, AssetID,FROM #TempItems TempTable Where (ID > @FirstRec AND ID < @LastRec)Order By ID ASC Tara KizerMicrosoft MVP for Windows Server System - SQL Serverhttp://weblogs.sqlteam.com/tarad/Database maintenance routines:http://weblogs.sqlteam.com/tarad/archive/2004/07/02/1705.aspx |
 |
|
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.CheersDaze. |
 |
|
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 KizerMicrosoft MVP for Windows Server System - SQL Serverhttp://weblogs.sqlteam.com/tarad/Database maintenance routines:http://weblogs.sqlteam.com/tarad/archive/2004/07/02/1705.aspx |
 |
|
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. |
 |
|
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. |
 |
|
|