I have an application in which I need to display \"pages\" of data in a list. The basic idea is fairly common. The display shows a list of items and at the bottom of the dis
I wish there were something a bit more elegant than this. This is my stored proc solution. The best my lame SQL skills can conjure up.
The OUT parameter in the parameter list is for the total rows in this set so the front end knows how many pages all together with this particular filter set.
CREATE PROC [dbo].[procCampaignGEDPushSelect]
@LastName VARCHAR(50) = null
,@FirstName VARCHAR(50) = null
,@Location VARCHAR(255) = null
,@DoB DateTime = null
,@Zip VARCHAR(50) = null
,@Phone VARCHAR(50) = null
,@Email VARCHAR(255) = null
,@Gender VARCHAR(20) = null
,@IsGED Bit = 0
,@IsBTT Bit = 0
,@IsOACE Bit = 0
,@Completed Bit = 0
,@TotalCount INT OUT
AS
BEGIN
SELECT @LastName = @LastName + '%'
SELECT @FirstName = @FirstName + '%'
SELECT @Location = @Location + '%'
SELECT @Zip = @Zip + '%'
SELECT @Phone = @Phone + '%'
SELECT @Email = @Email + '%'
SELECT @Gender = @Gender + '%'
SELECT row_number() OVER (ORDER BY LastName, FirstName, DoB) AS RowNumber
, TPT.LastName
, TPT.FirstName
, TPT.WF1Site
, TPT.DOB
, TPT.Zip
, TPT.Telephone
, TPT.CellPhone
, TPT.Email
, TPT.Gender
, TPT.IsBTT
, TPT.IsGED
, TPT.IsOACE
, TPT.IsSRS
,CGP.*
FROM tblCampaignGEDPush CGP
JOIN tblParticipants TPT
ON CGP.PartID = TPT.PartID
WHERE 1=1
AND 1 = (CASE WHEN @LastName IS NOT NULL THEN (CASE WHEN TPT.LastName LIKE @LastName THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @FirstName IS NOT NULL THEN (CASE WHEN TPT.FirstName LIKE @Firstname THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @Location IS NOT NULL THEN (CASE WHEN TPT.WF1Site LIKE @Location THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @Zip IS NOT NULL THEN (CASE WHEN TPT.Zip LIKE @Zip THEN 1 ELSE 0 END) ELSE 1 END)
AND
( 1 = (CASE WHEN @Phone IS NOT NULL THEN (CASE WHEN TPT.Telephone LIKE @Phone THEN 1 ELSE 0 END) ELSE 1 END)
OR 1 = (CASE WHEN @Phone IS NOT NULL THEN (CASE WHEN TPT.CellPhone LIKE @Phone THEN 1 ELSE 0 END) ELSE 1 END)
)
AND 1 = (CASE WHEN @Email IS NOT NULL THEN (CASE WHEN TPT.Email LIKE @Email THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @Gender IS NOT NULL THEN (CASE WHEN TPT.Gender LIKE @Gender THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @DoB IS NOT NULL THEN (CASE WHEN TPT.DoB = @DoB THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @IsGED != 0 THEN (CASE WHEN TPT.IsGED = 1 THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @IsBTT != 0 THEN (CASE WHEN TPT.IsBTT = 1 THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @IsOACE != 0 THEN (CASE WHEN TPT.IsOACE = 1 THEN 1 ELSE 0 END) ELSE 1 END)
AND 1 = (CASE WHEN @Completed != 0 THEN (CASE WHEN CGP.Completed = 1 THEN 1 ELSE 0 END) ELSE 1 END)
ORDER BY TPT.LastName
, TPT.FirstName
, TPT.DoB
SELECT @TotalCount = @@ROWCOUNT
END
So then I got started thinking. Rather than use this tricky, bug-prone proc (which by the way works fairly well), since I am in .NET, I wonder if there is a nice tight solution there.
Now I know the original question has nothing to do with .NET, so I'm leaving the above proc available for those interested in the strict SQL solution, which, I think, works fairly well.
So I started digging into the IQueryable interface and struck gold:
IQueryable<queryParticipant> qparticipant = db.queryParticipants.AsQueryable();
...
qparticipant = qparticipant.Where( ... any filter you choose );
...
return qparticipant
.OrderBy( p => p.LastName )
.OrderBy( p => p.FirstName )
.OrderBy( p => p.DOB )
.Select( ... whatever you like ... )
.Skip( StartRecordNumber ) // This is the trick! Start the query here..
.Take( PageSize ) // Take only as many as you need
;
And that's it. The .NET approach is nice if available. The Stored Proc is great when such an API is not available.
Something like this should do...
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY LastName, FirstName, DoB) AS __RN
FROM CampaignParticipants
WHERE LastName LIKE 'R%') innerData WHERE __RN BETWEEN 1 and 100
However, you should be using the column names, not '*'. I don't know what your tables look like so I can't fill that in for you.
First of all try to use the proc instead of view and as users are asking you to have so much filtering then proc is only solution you got.Inside proc filter the data using all these filters and then generate the row_number and then show say first 100 records or like that.