I'm currently implementing a search function in one of our grids and when doing so, my query goes from running in 1 second or less to running in about 16 seconds (I've added suggested indices, etc). The data returned from this query will be the parent's id, parent's name, most recent child's first name and most recent child's last name. The following simplified query runs extremely slow (15+ seconds) but functions correctly:
SELECT
p.id
,p.name
,c.firstname
,c.lastname
FROM Parents p
CROSS APPLY (
SELECT TOP (1)
c.firstname
,c.lastname
FROM Children c
WHERE c.ParentId = p.Id
ORDER BY c.datecreated DESC
) i
INNER JOIN Users s
ON p.UserId = u.Id
WHERE (
@search IS NOT NULL
AND @search != ''
AND (
@search = c.firstname
OR @search = c.lastname
OR p.name = @search
)
OR @search IS NULL
OR @search = ''
)
The following query (notice the first name and last name searching is not included) runs quickly but is missing desired functionality:
SELECT
p.id
,p.name
,c.firstname
,c.lastname
FROM Parents p
CROSS APPLY (
SELECT TOP (1)
c.firstname
,c.lastname
FROM Children c
WHERE c.ParentId = p.Id
ORDER BY c.datecreated DESC
) i
INNER JOIN Users s
ON p.UserId = u.Id
WHERE (
@search IS NOT NULL
AND @search != ''
AND p.name = @search
)
OR (@search IS NULL)
OR (@search = '')
How can I optimize my searching query such that it runs quickly? In practice, there are many other joins and much more activity in my query however I believe this to be the issue as when I comment out the first and last name searching, my query runs very quickly.
All help is appreciated.
EDIT: I've also tried with an inner join and subquery as shown below however this produced even worse results than the lateral join attempt originally shown (~25 second execution time)
SELECT
p.id,
p.name,
c.firstname,
c.lastname
from Parents P
INNER JOIN children c
ON c.ParentId = p.Id
INNER JOIN Users s
ON p.UserId = s.Id
WHERE c.datecreated = (
select max(c1.datecreated) from children c1 where c1.ParentId = c.ParentId
)
and @search IS NOT NULL
AND @search != ''
AND (
@search = c.firstname
OR @search = c.lastname
OR p.name = @search
)
OR @search IS NULL
OR @search = ''
)