Isso está fazendo minha cabeça, mas estou preso em tentar obter um Index Seek no agregado MAX dentro desta consulta.
Aqui está o plano de execução - e estou me perguntando o que estou perdendo aqui, pois atualmente a consulta leva 3/4 segundos para ser concluída, o que é muito lento. Eu indexei em StartDate, ClientID sem sorte.
CREATE TABLE #SearchWords
(
ID int IDENTITY(1,1),
Word NVARCHAR(50)
)
INSERT INTO #SearchWords
(
Word
)
SELECT
value
FROM
STRING_SPLIT(@SearchWords, ' ')
WHERE
TRIM(value) <> ''
SELECT
C.ClientID,
C.FirstName,
C.LastName,
C.FullName,
C.DateOfBirth,
G.GenderName,
G.GenderIcon,
C.VerificationCode,
MAX(V.StartDate) as LastVisitDate
FROM
Client C
LEFT JOIN Visit V on
C.ClientID = V.ClientID
INNER JOIN LookUp.Gender G on
C.GenderID = G.GenderID
WHERE
(
EXISTS( -- if we have words
SELECT *
FROM #SearchWords s
WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
)
OR
(SELECT COUNT(*) FROM #SearchWords)=0 -- if we haven't any words
)
AND DateOfBirth BETWEEN ISNULL(@LowerDate,DateOfBirth) AND ISNULL(@UpperDate,DateOfBirth)
GROUP BY
C.ClientID,
C.FirstName,
C.LastName,
C.FullName,
C.DateOfBirth,
G.GenderName,
G.GenderIcon,
C.VerificationCode
Você deseja que seu índice tenha ClientID como a chave principal. Por exemplo:
CREATE INDEX IX_Visit_ClientID_StartDate ON Visit(ClientID, StartDate)
Isso ocorre porque você precisa ingressar no ClientID antes de encontrar a StartDate mais recente. Portanto ClientID precisa aparecer primeiro.
Junto com essa mudança de índice... Como você só quer encontrar o mais recente
Visit.StartDate
, você pode mudar o seuLEFT JOIN Visit
para umOUTER APPLY
que obtenha a data mais recente.Tente isto:
O
GROUP BY
é quase certamente desnecessário agora também. Remova-o se estiver.Fora do assunto:
Um último comentário final que tecnicamente não está relacionado à sua pergunta. Você parece estar fazendo algo para o qual a pesquisa de texto completo pode ser uma solução melhor.