Desafortunadamente, parece que no hay forma de crear un filtro negativo para un índice, sin recurrir a la creación de una vista materializada. Si fuera posible crear un filtro negativo como el que le gustaría, sería muy difícil para el optimizador de consultas "elegir" el índice para su uso, aumentando drásticamente el tiempo requerido para encontrar un buen plan.
Dependiendo de los patrones de consulta para esta tabla, simplemente podría crear dos índices; uno por menos de 9 y uno para mayor que 14. Cualquiera de estos índices puede ser elegido por el optimizador de consultas para simples WHERE
cláusulas tales comoWHERE StatusID = 6
CREATE TABLE dbo.TestNegativeFilter
(
TestNegativeFilter INT NOT NULL
CONSTRAINT PK_TestNegativeFilter
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, StatusID INT NOT NULL
);
GO
CREATE INDEX IX_TestNagativeFilter_LessThan9
ON dbo.TestNegativeFilter(StatusID)
WHERE (StatusID < 9);
CREATE INDEX IX_TestNagativeFilter_GreaterThan14
ON dbo.TestNegativeFilter(StatusID)
WHERE (StatusID > 14);
Otra forma de lograr esto podría ser:
CREATE INDEX IX_TestNegativeFilter_9_to_14
ON dbo.TestNegativeFilter(StatusID)
WHERE (StatusID IN (9, 10, 11, 12, 13, 14));
SELECT *
FROM dbo.TestNegativeFilter tnf
EXCEPT
SELECT *
FROM dbo.TestNegativeFilter tnf
WHERE tnf.StatusID IN (9, 10, 11, 12, 13, 14);
Esto usa el índice filtrado del 9 al 14 para excluir filas.
En mi plataforma de prueba, un índice de cobertura simple devuelve filas, con mucho, la más rápida:
CREATE NONCLUSTERED INDEX IX_TestNegativeFilter_StatusID
ON dbo.TestNegativeFilter(StatusID)
INCLUDE (TestNegativeFilter);
SELECT *
FROM dbo.TestNegativeFilter tnf
WHERE tnf.StatusID NOT IN (9, 10, 11, 12, 13, 14);
Alternativamente, usando una variación en el enfoque utilizado en su propia respuesta :
CREATE INDEX [IX dbo.TestNegativeFilter StatusID not 9-14]
ON dbo.TestNegativeFilter (StatusID)
WHERE StatusID <> 9
AND StatusID <> 10
AND StatusID <> 11
AND StatusID <> 12
AND StatusID <> 13
AND StatusID <> 14;
A pesar de que el filtro se escribe como conjunciones, admite consultas escritas de cualquiera de las siguientes maneras (la primera es un poco más eficiente):
StatusID NOT IN (9, 10, 11, 12, 13, 14)
StatusID < 9 OR StatusID > 14
StatusID NOT BETWEEN 9 AND 14