Feragatname : Bu cevaptaki bazı şeyler bir DBA çakması yapabilir. Saf performans açısından yaklaşıyorum - her zaman Index Scans aldığınızda Index Seeks'i nasıl edinirim.
Yoldan çekilince, işte gidiyor.
Sorgunuz, "çeşitli mutfak arama sorgusu" olarak bilinir. Bu, bir dizi olası arama koşulunu karşılamayı amaçlayan tek bir sorgudur. Kullanıcı @status
bir değere ayarlanırsa , bu duruma filtre uygulamak istersiniz. Öyleyse @status
, NULL
tüm durumları döndürün, vb.
Bu, indeksleme ile ilgili sorunlar getirir, ancak tüm arama koşullarınız "eşittir" ölçütleri olduğu için bu durumla ilgili değildir.
Bu anlaşılabilir:
WHERE [status]=@status
SQL Server'ın dizinde tek bir değer aramak yerine her satır için değerlendirilmesi gerektiğinden bu durum anlaşılmaz değilISNULL([status], 0)
:
WHERE ISNULL([status], 0)=@status
Mutfak lavabo problemini daha basit bir biçimde yeniden yarattım:
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);
Aşağıdakileri denerseniz, A, dizinin ilk sütunu olmasına rağmen bir Dizin Taraması alırsınız:
DECLARE @a int=4, @b int=NULL;
SELECT *
FROM #work
WHERE (@a IS NULL OR @a=A) AND
(@b IS NULL OR @b=B);
Ancak bu bir Dizin Araması üretir:
DECLARE @a int=4, @b int=NULL;
SELECT *
FROM #work
WHERE @a=A AND
@b IS NULL;
Yönetilebilir miktarda parametre kullandığınız sürece (sizin durumunuzda iki tane), muhtemelen sadece UNION
bir grup arama sorgusu yapabilirsiniz - temel olarak arama kriterlerinin tüm permütasyonları. Üç kriteriniz varsa, bu dağınık görünecek, dördü ile tamamen yönetilemeyecek. Uyarılmıştın.
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;
Bu dördünden üçüncüsünde Dizin Araması kullanmak için ikinci bir dizine ihtiyacınız olacak (B, A)
. Sorgunuz bu değişikliklerle nasıl görünebilir (sorguyu daha okunabilir hale getirmek için yeniden düzenlemem dahil).
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='');
... artı Employee
iki dizin sütunu ters çevrilmiş olarak ek bir dizine ihtiyacınız olacaktır .
Bütünlük için, bunun x=@x
dolaylı olarak x
olamayacağı anlamına gelir NULL
çünkü NULL
asla eşit değildir NULL
. Bu, sorguyu biraz basitleştirir.
Ve evet, Aaron Bertrand'ın dinamik SQL cevabı çoğu durumda daha iyi bir seçimdir (yani, yeniden derlemelerle yaşayabildiğinizde).
@Status
misiniz?