Solved

Problem regarding stored procedure paging.

Posted on 2007-03-23
3
274 Views
Last Modified: 2008-02-01
We are using SQL 2000 and have many pages where we required stored proc paging.  We're currently using this template to provide our paging:

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

DECLARE @first_id int, @startRow int
      
-- A check can be added to make sure @startRowIndex isn't > count(1)
-- from employees before doing any actual work unless it is guaranteed
-- the caller won't do that

-- Get the first employeeID for our page of records
SET ROWCOUNT @startRowIndex
SELECT @first_id = employeeID FROM employees ORDER BY employeeid

-- Now, set the row count to MaximumRows and get
-- all records >= @first_id
SET ROWCOUNT @maximumRows

SELECT e.*, d.name as DepartmentName
FROM employees e
   INNER JOIN Departments D ON
       e.DepartmentID = d.DepartmentID
WHERE employeeid >= @first_id
ORDER BY e.EmployeeID

SET ROWCOUNT 0

GO

This method is very fast and easy to use but the problem with it is that it stores the unique column ID as a start and end point on where to get page 2, page 3 etc.  It only works when you're bring back results that are ASC or DESC on a incremental unique column.  

We want to find a very fast solution to paging like this but with different sorting.  We want to bring back members who have updated their profile recently, or were online, which means their unique id's won't be incremental anymore.  

A) Is it wise to use the above paging method for columns other than unique ID's and if so, how would we go about it.

B) Is there a better paging solution out there?
0
Comment
Question by:Tsoukias
  • 2
3 Comments
 
LVL 42

Expert Comment

by:dqmq
ID: 18781979
OK, I"ll give it a shot. Pardon any typo's because I don't have a system to test right now.

First, adapt your given example to dyanamically generate rownumber independent of the employeeID. That looks like this:

CREATE  PROCEDURE [dbo].[usp_PageResults_NAI]
(
    @startRowIndex int,
    @maximumRows int
)
AS      
SELECT e.*, d.name as DepartmentName
--derive ordinal rownum from employeeID sequence, which is a unique key
, (select count (*)+1 from FROM employees e2            
      inner join departments d2 on e2.departmentID = d2.departmentID
      where e2.employeeID < e.employeeID
  )  as rownum
FROM employees e
   INNER JOIN Departments D ON
       e.DepartmentID = d.DepartmentID
WHERE rownum between  @startRowIndex and (@startRowIndex + @maximumRows  - 1)
ORDER BY e.EmployeeID

Then expand to support a different sort. For this example, I will sort by Dept Name


CREATE  PROCEDURE [dbo].[usp_PageResults_NAI_byDept ]
(
    @startRowIndex int,
    @maximumRows int
)
AS      
SELECT e.*, d.name as DepartmentName
--derive ordinal rownum, this time from name.  Since name is not unique, use the unique key
--employeeID as a tie breaker
, (select count (*)+1 from FROM employees e2
      inner join departments d2 on e2.departmentID = d2.departmentID
      where d2.name < d.name
            or (d2.name = d.name and e2.employeeID < e2.employeeID)  -- tie breaker
  )  as rownum
FROM employees e
   INNER JOIN Departments D ON
       e.DepartmentID = d.DepartmentID
WHERE rownum between  @startRowIndex and (@startRowIndex + @maximumRows  - 1)
ORDER BY d.Name, e.employeeID      

Note the essence of the solution comes from how rownum is generated by the inner select. Once you 'get' the idea, you can make the inner select order asc or desc by any column or columns you like, provided you use the unique key to break any ties.

good luck
--dQmQ  


0
 

Author Comment

by:Tsoukias
ID: 18784367
That solution looks definitely along the lines of what I was hoping for - but I forgot to mention that ideally I'd like a dynamic solution, ie, passing in the column I wanted to order/sort on?  Is this going to be possible?
0
 
LVL 42

Accepted Solution

by:
dqmq earned 125 total points
ID: 18801532
1. To support dynamic paging, I incorporated a view. The basic view is shown below.  You may need to tweak it a bit to include all of the columns you want.  The purpose of the view is so that when you get to the dynamic SQL, all columns can be referenced by the same table alias.

CREATE VIEW [dbo].[EmployeeDepartmentsView]
AS
SELECT e.*, d.Name FROM employees e
   INNER JOIN Departments d ON
       e.DepartmentID = d.DepartmentID
GO


2. Then modify the (non-dynamic) SQL to use the view.  Get this working to your satisfaction before
moving to step 3.

CREATE  PROCEDURE [dbo].[usp_PageResults_NAI ]
(
    @startRowIndex int,
    @maximumRows int,
)
AS
SELECT *
, (select count (*)+1
   from EmployeeDepartmentsView v2
   where v2.name < v1.name
            or (v2.name = v1.name and v2.employeeID < v1.employeeID)  
  )  as rownum
FROM EmployeeDepartmentsView V1
WHERE rownum between  @startRowIndex and (@startRowIndex + @maximumRows  - 1)
ORDER BY v1.Name, v1.employeeID

3.  OK, now introduce the additional parameter and dynamic SQL

CREATE  PROCEDURE [dbo].[usp_PageResults_NAI ]
(
    @startRowIndex int,
    @maximumRows int,
    @sortColumn varchar(128) = 'EmployeeID'
)
AS
DECLARE @sql VARCHAR(8000)
SET @sql = '
 SELECT *, (select count (*)+1
 FROM EmployeeDepartmentsView v2
 WHERE '
    +  ' v2.'  + @sortcolumn
    + ' < v1.' + @sortcolumn
    + ' or (v2.' + @sortcolumn
    + ' = v1.' + @sortcolumn + '
  AND v2.employeeID < v1.employeeID)) AS rownum
  FROM EmployeeDepartmentsView V1
  WHERE rownum between  @startRowIndex and (@startRowIndex + @maximumRows  - 1)
  ORDER BY v1.Name, v1.employeeID'

SELECT @sql  --for testing only
EXEC (@sql)  


     
0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
DTS Connection Failed 7 70
SQL Improvement  ( Speed) 14 28
SSRS Enable Remote Errors 4 26
Need help with a Stored Proc on Sql Server 2012 4 10
Nowadays, some of developer are too much worried about data. Who is using data, who is updating it etc. etc. Because, data is more costlier in term of money and information. So security of data is focusing concern in days. Lets' understand the Au…
Everyone has problem when going to load data into Data warehouse (EDW). They all need to confirm that data quality is good but they don't no how to proceed. Microsoft has provided new task within SSIS 2008 called "Data Profiler Task". It solve th…
This video shows how to set up a shell script to accept a positional parameter when called, pass that to a SQL script, accept the output from the statement back and then manipulate it in the Shell.
Via a live example, show how to setup several different housekeeping processes for a SQL Server.

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question