Isenção de responsabilidade : algumas das coisas nesta resposta podem fazer um DBA recuar. Estou abordando isso do ponto de vista do desempenho puro - como obter pesquisas de índice quando você sempre obtém verificações de índice.
Com isso fora do caminho, aqui vai.
Sua consulta é conhecida como "consulta de pia da cozinha" - uma consulta única destinada a atender a várias condições possíveis de pesquisa. Se o usuário definir @statusum valor, você deseja filtrar esse status. Se @statusestiver NULL, retorne todos os status e assim por diante.
Isso apresenta problemas com a indexação, mas eles não estão relacionados à capacidade de Sargability, porque todas as suas condições de pesquisa são "iguais a" critérios.
Isso é sargável:
WHERE [status]=@status
Isso não é sargável porque o SQL Server precisa avaliar ISNULL([status], 0)para cada linha em vez de procurar um único valor no índice:
WHERE ISNULL([status], 0)=@status
Recriei o problema da pia da cozinha de uma forma mais simples:
CREATE TABLE #work (
A int NOT NULL,
B int NOT NULL
);
CREATE UNIQUE INDEX #work_ix1 ON #work (A, B);
INSERT INTO #work (A, B)
VALUES (1, 1), (2, 1),
(3, 1), (4, 1),
(5, 2), (6, 2),
(7, 2), (8, 3),
(9, 3), (10, 3);
Se você tentar o seguinte, você obterá uma verificação de índice, mesmo que A seja a primeira coluna do índice:
DECLARE @a int=4, @b int=NULL;
SELECT *
FROM #work
WHERE (@a IS NULL OR @a=A) AND
(@b IS NULL OR @b=B);
Isso, no entanto, produz uma busca por índice:
DECLARE @a int=4, @b int=NULL;
SELECT *
FROM #work
WHERE @a=A AND
@b IS NULL;
Enquanto você estiver usando uma quantidade gerenciável de parâmetros (dois no seu caso), provavelmente poderá fazer UNIONvárias consultas de pesquisa - basicamente todas as permutações dos critérios de pesquisa. Se você tiver três critérios, isso parecerá confuso; com quatro, será completamente incontrolável. Voce foi avisado.
DECLARE @a int=4, @b int=NULL;
SELECT *
FROM #work
WHERE @a=A AND
@b IS NULL
UNION ALL
SELECT *
FROM #work
WHERE @a=A AND
@b=B
UNION ALL
SELECT *
FROM #work
WHERE @a IS NULL AND
@b=B
UNION ALL
SELECT *
FROM #work
WHERE @a IS NULL AND
@b IS NULL;
Para o terceiro desses quatro usar uma busca de índice, você precisará de um segundo índice (B, A). Veja como sua consulta pode parecer com essas alterações (incluindo minha refatoração da consulta para torná-la mais legível).
DECLARE @Status int = NULL,
@IsUserGotAnActiveDirectoryUser bit = NULL;
SELECT [IdNumber], [Code], [Status], [Sex], [FirstName], [LastName],
[Profession], [BirthDate], [HireDate], [ActiveDirectoryUser]
FROM Employee
WHERE [Status]=@Status AND
@IsUserGotAnActiveDirectoryUser IS NULL
UNION ALL
SELECT [IdNumber], [Code], [Status], [Sex], [FirstName], [LastName],
[Profession], [BirthDate], [HireDate], [ActiveDirectoryUser]
FROM Employee
WHERE [Status]=@Status AND
@IsUserGotAnActiveDirectoryUser=1 AND ActiveDirectoryUser<>''
UNION ALL
SELECT [IdNumber], [Code], [Status], [Sex], [FirstName], [LastName],
[Profession], [BirthDate], [HireDate], [ActiveDirectoryUser]
FROM Employee
WHERE [Status]=@Status AND
@IsUserGotAnActiveDirectoryUser=0 AND (ActiveDirectoryUser IS NULL OR ActiveDirectoryUser='')
UNION ALL
SELECT [IdNumber], [Code], [Status], [Sex], [FirstName], [LastName],
[Profession], [BirthDate], [HireDate], [ActiveDirectoryUser]
FROM Employee
WHERE @Status IS NULL AND
@IsUserGotAnActiveDirectoryUser IS NULL
UNION ALL
SELECT [IdNumber], [Code], [Status], [Sex], [FirstName], [LastName],
[Profession], [BirthDate], [HireDate], [ActiveDirectoryUser]
FROM Employee
WHERE @Status IS NULL AND
@IsUserGotAnActiveDirectoryUser=1 AND ActiveDirectoryUser<>''
UNION ALL
SELECT [IdNumber], [Code], [Status], [Sex], [FirstName], [LastName],
[Profession], [BirthDate], [HireDate], [ActiveDirectoryUser]
FROM Employee
WHERE @Status IS NULL AND
@IsUserGotAnActiveDirectoryUser=0 AND (ActiveDirectoryUser IS NULL OR ActiveDirectoryUser='');
... mais você precisará de um índice adicional Employeecom as duas colunas de índice invertidas.
Para completar, devo mencionar que x=@ximplicitamente significa que xnão pode ser NULLporque NULLnunca é igual a NULL. Isso simplifica um pouco a consulta.
E sim, a resposta SQL dinâmica de Aaron Bertrand é uma escolha melhor na maioria dos casos (ou seja, sempre que você pode conviver com as recompilações).
@Status?