August 4, 2005 at 1:55 am
Hi,
I have the following problem and wonder if someone can shed some light on it (Sql Server 2000).
My application allows the user to pass in the first letter of a customer surname, All customers or part of a surname and the appropriate results are then returned. Now they would like to optionally choose the column (at the moment if searching for a partial match only the surname can be used)
Any suggestions on how to do this. I suspect I will need to use some sort of dynamic code, but am not sure what.
SP as it currently stands: -
CREATE PROCEDURE [dbo].[prc0001CustomerMasterList]
(@strFirstLetter char(10),
@strFindName varchar(100) )
AS
If @strFindName = '' -- NOT SEARCHING FOR A NAME OR PART OF A NAME--
Begin
If @strFirstLetter = 'All' -- ALL CUSTOMERS REGARDLESS OF SPECIFIED LETTER --
Begin
Select A.intClientID,
A.intCaseNo,
A.intRecordedBy,
B.strSurname + ': ' + B.strForename as strRecordedBy,
A.intStatusID,
IsNull(C.strDescription, 'Uknown Status') as strStatus,
A.strTitle,
A.strSurname,
A.strFirstname,
A.strSecondName,
A.dtDOB,
A.strAddressLine1,
A.strHomeTel,
SubString(A.strRemarks, 1, 1) as strRemarks,
33554432 as color,
0 as found,
0 as selected
From tblCustomer A Left Outer Join
tblStaff B On A.intRecordedBy = B.intStaffID Left Outer Join
tblCustomerStatus C on A.intStatusID = C.intStatusID
Order By A.strSurname,
A.strFirstname,
A.strSecondName,
A.dtDOB
End
Else -- ALL CUSTOMERS STARTING WITH SPECIFIED LETTER --
Begin
Select A.intClientID,
A.intCaseNo,
A.intRecordedBy,
B.strSurname + ': ' + B.strForename as strRecordedBy,
A.intStatusID,
IsNull(C.strDescription, 'Uknown Status') as strStatus,
A.strTitle,
A.strSurname,
A.strFirstname,
A.strSecondName,
A.dtDOB,
A.strAddressLine1,
A.strHomeTel,
SubString(A.strRemarks, 1, 1) as strRemarks,
33554432 as color,
0 as found,
0 as selected
From tblCustomer A Left Outer Join
tblStaff B On A.intRecordedBy = B.intStaffID Left Outer Join
tblCustomerStatus C on A.intStatusID = C.intStatusID
Where SubString(A.strSurname,1,1) = @strFirstLetter
Order By A.strSurname,
A.strFirstname,
A.strSecondName,
A.dtDOB
End
End
Else -- SEARCHING FOR A NAME OR PART OF A NAME--
Begin
Select A.intClientID,
A.intCaseNo,
A.intRecordedBy,
B.strSurname + ': ' + B.strForename as strRecordedBy,
A.intStatusID,
IsNull(C.strDescription, 'Uknown Status') as strStatus,
A.strTitle,
A.strSurname,
A.strFirstname,
A.strSecondName,
A.dtDOB,
A.strAddressLine1,
A.strHomeTel,
SubString(A.strRemarks, 1, 1) as strRemarks,
33554432 as color,
0 as found,
0 as selected
From tblCustomer A Left Outer Join
tblStaff B On A.intRecordedBy = B.intStaffID Left Outer Join
tblCustomerStatus C on A.intStatusID = C.intStatusID
Where A.strSurname Like @strFindName
Order By A.strSurname,
A.strFirstname,
A.strSecondName,
A.dtDOB
End
GO
Any help most appreciated.
Thanks
CCB
August 4, 2005 at 2:14 am
Instead of
Where SubString(A.strSurname,1,1) = @strFirstLetter
I think I would write something like
Where
(SubString(A.strSurname,1,1) = @strFirstLetter and @SearchCol = 'SurName')
or
(SubString(A.strFirstname,1,1) = @strFirstLetter and @SearchCol = 'FirstName')
A similar change can be applied in the last section (where you use search like).
I think you should also consider rewriting your sp such that you don't have the same select 3 times with different where clauses. The same method - including variables in your where clause - can be applied. Let me know if you need help.
August 4, 2005 at 6:05 am
Hi,
That works a treat. I have changed the rest so that there is only one select statement.
Thanks for your help.
CCB
August 5, 2005 at 12:59 am
instead of
Where
(SubString(A.strSurname,1,1) = @strFirstLetter and @SearchCol = 'SurName')
or
(SubString(A.strFirstname,1,1) = @strFirstLetter and @SearchCol = 'FirstName')
I would first replace append a '%' to the @strFirstLetter then write:
Where
(A.strSurname like @strFirstLetter and @SearchCol='SurName')
or
(A.strFirstname like @strFirstLetter and @SearchCol='FirstName')
Reason being the SubString function or any function for that matter will suppresss any indexes you put on that column, causing a full table scan or index scan.
August 5, 2005 at 1:02 am
better yet, the where order should be changed to:
Where
(@SearchCol='SurName' and A.strSurname like @strFirstLetter)
or
(@SearchCol='FirstName' and A.strFirstname like @strFirstLetter )
This way, the db can make better use of short circuiting, so that the second condition is not evaluated if the first condition is false.
August 5, 2005 at 1:18 am
Sounds reasonable - still I didn't know Thanks for the tips
August 5, 2005 at 7:23 am
This way, the db can make better use of short circuiting, so that the second condition is not evaluated if the first condition is TRUE.
August 5, 2005 at 7:30 am
I think he means
such that "A.strSurname like @strFirstLetter" will not be evaluated if "@SearchCol='SurName'" is false
August 5, 2005 at 7:33 am
oops... but now if someone understands it like me he'll know about it both ways .
August 5, 2005 at 7:36 am
Yeah, it wasn't because what you said didn't make sense
See you all in 3 weeks (vacation )
Jesper
August 5, 2005 at 10:54 am
Hi all,
I meant exactly what i wrote
Where
(@SearchCol='SurName' and A.strSurname like @strFirstLetter)
or
(@SearchCol='FirstName' and A.strFirstname like @strFirstLetter )
This way, the db can make better use of short circuiting, so that the second condition is not evaluated if the first condition is false.
False AND ? = FALSE
True AND True/False = TRUE/FALSE depending on the second condition
So as soon as the first condition is FALSE then the second condition will not be evaluated.
If it's a OR, then only if the first condition is TRUE ; the second condition is not evaluated
TRUE AND ? = TRUE
FALSE AND ? = TRUE/FALSE depending on second condition
August 5, 2005 at 11:17 am
Ya I got what you really meant 2 minutes too late .
Viewing 12 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic. Login to reply