I have a scenario where SQL server using table valued function with joins to many other tables. The function returns many columns, which are not always desirable output for every report, causing lots of IO.
Is it better to copy the query inside the function and output the result to temp table (with required columns and filter conditions only) and Join to other tables as required or is it OK to use the table valued function?
I understand generalizing code inside Table valued function is good attempt to control making code changes every where if logic changes.
Generalizing code and performance are both important to me, should I choose between them or is there other ways to improve performance in SQL server in such cases ?
Below is the sample query I often use with sample table valued function
--table valued function(used by many other sps as general procedure)
CREATE FUNCTION [dbo].[TfPersonDataSel]
( @UserPersonId INT )
RETURNS TABLE
AS
RETURN ( SELECT p.PersonId ,
p.FirstName ,
p.MiddleName ,
p.LastName ,
p.[Name] ,
p.Name2 ,
p.SSN ,
p.TIN ,
p.OrganizationId ,
p.Title ,
p.UserPersonId ,
p.InsertDate ,
p.ReferenceId ,
p.ReferenceNote ,
o.OfficeId ,
o.Office ,
c.Alias ,
c.OrganizationId AS TenantOrganizationId ,
z.Organization ,
li.ListItem AS Entity ,
u.UserName ,
u.[Password] ,
li2.ListItem AS UserStatus ,
mp.[Value] Phone ,
em.[Value] Email ,
a.AddressId ,
a.Address1 ,
a.Address2 ,
a.City ,
a.ZipCode ,
a.StateId ,
s.StateCode ,
pdt.[Date] AS HiredDate ,
pe.DateOfBirth
FROM dbo.Person AS p
INNER JOIN dbo.PersonCurrent AS pc ON p.PersonId = pc.PersonId
INNER JOIN dbo.[User] AS u ON p.PersonId = u.PersonId
INNER JOIN dbo.Office AS o ON pc.OfficeId = o.OfficeId
INNER JOIN dbo.TenantOrganization AS c ON o.OrganizationId = c.OrganizationId
INNER JOIN dbo.Organization AS z ON c.OrganizationId = z.OrganizationId
INNER JOIN dbo.ListItem AS li ON pc.EntityListItemId = li.ListItemId
INNER JOIN dbo.ListItem AS li2 ON u.StatusListItemId = li2.ListItemId
LEFT JOIN dbo.PersonEEO AS pe ON pe.PersonId = p.PersonId
LEFT JOIN dbo.Address AS a ON pc.AddressId = a.AddressId
LEFT JOIN dbo.State AS s ON s.StateId = a.StateId
LEFT JOIN dbo.ContactInformation AS mp ON mp.ContactInformationId = pc.PhoneContactInformationId
LEFT JOIN dbo.ContactInformation AS em ON em.ContactInformationId = pc.EmailContactInformationId
LEFT JOIN dbo.PersonDateType AS pdt
INNER JOIN dbo.ListItem AS li3 ON li3.ListItemId = pdt.DateTypeListItemId
AND li3.ListItem = 'HiredDate' ON pdt.PersonId = p.PersonId
WHERE ( EXISTS ( SELECT TOP 1 1
FROM dbo.TfPersonDataAccessSel (@UserPersonId, 1) AS t
INNER JOIN dbo.PersonNode AS pn ON pn.NodeId = t.NodeId
WHERE p.PersonId = pn.PersonId )
OR EXISTS ( SELECT TOP 1 1
FROM dbo.TfPersonDataAccessSel (@UserPersonId, 1) AS t
INNER JOIN dbo.PersonDataAccess AS pn ON pn.NodeId = t.NodeId
WHERE p.PersonId = pn.PersonId )));
--table valued function call like:
SELECT DISTINCT t.PersonId ,
t.[Name]
FROM dbo.TfPersonDataSel (@UserPersonId) AS t
INNER JOIN dbo.OfficeStaff AS os ON os.PersonId = t.PersonId
ORDER BY t.[Name];