I have two tables A and B. Both tables have more than 2 lacs records.
Lets say f1 is the field in B, and f1 is varchar field. For each value in f1, we are searching the corresponding record id in A. We have used a scalar function say GetcorrespondingID(B.f1). In Join query we are using condition as GetcorrespondingID(B.f1) = A.RecordID.
After using this function query becomes dam slow. Please advise is there any alternate way?
Hard to say without knowing quite a bit more. In general, scalar functions slow things down. If you post both the query using the function and the function definition, it would help. There's probably another way
Insert @tblchangeFrom
Select distinct me.EMPID, ChangedFrom, COALESCE(me.OutlookPreferredName,me.NAME_COMBINED,'N/A') AS [BackUp 1]
from @tblAudit ad join Employee me
on
dbo.Employee(Ad.empfName) = me.EMPID
FUNCTION [dbo].Employee]
( @Name varchar(100)
)
RETURNS VARCHAR(8)
AS
BEGIN
Declare @ReturnValue varchar(8)
SELECT @ReturnValue = EMPID FROM MDREmployee WHERE ltrim(rtrim(name_last))+', '+ltrim(rtrim(name_first)) = @Name OR OutlookPreferredName = @Name OR name_combined = @Name
Return @ReturnValue
END
Try making the function into an inline function like shown below
CREATE FUNCTION [dbo].[Employee] ( @Name VARCHAR(100) )
RETURNS TABLE
AS
RETURN
SELECT TOP (1) EMPID
FROM MDREmployee
WHERE LTRIM(RTRIM(name_last)) + ', ' + LTRIM(RTRIM(name_first)) = @Name
OR OutlookPreferredName = @Name
OR name_combined = @Name
GO
Then, instead of joining like what you are doing
dbo.Employee(B.f1) = A.RecordID.
join like shown below
(SELECT EMPID FROM dbo.Employee(B.f1)) = A.RecordID
If you query without using the function, is it faster? If you haven't tried that, what I am thinking is something like this:
SELECT
-- your other columns ,
x.EMPID
FROM
YourOtherTablesAndJoins
OUTER APPLY
(
SELECT TOP (1) EMPID
FROM MDREmployee x
WHERE LTRIM(RTRIM(x.name_last)) + ', ' + LTRIM(RTRIM(x.name_first)) = b.f1
OR x.OutlookPreferredName = b.f1
OR x.name_combined = b.f1
) AS x
You really need to restructure the lookup table to have a single name column that contains all the possible lookup values. That is, create another table, which can be maintained by a trigger, that inserts the values of name_combined, OutlookPreferredName, and ltrim(rtrim(name_last))+', '+ltrim(rtrim(name_first)) into a single column. Cluster the lookup table on that column. Then the lookup becomes a simple keyed search:
SELECT TOP (1) EMPID
FROM dbo.MDREmployeeNameLookup
WHERE
lookup_name = @Name
Until then, this may be the best you can do:
ALTER FUNCTION [dbo].Employee
(
@Name varchar(100)
)
RETURNS varchar(8)
AS
BEGIN
RETURN (
SELECT EMPID
FROM dbo.MDREmployee
WHERE
@Name IN (name_combined, OutlookPreferredName, ltrim(rtrim(name_last))+', '+ltrim(rtrim(name_first)))
)
END