2

在asp中,我設置了幾個下拉菜單,允許用戶根據選擇來篩選頁面上顯示的數據。SQL優化where條款中的條件

這些下拉列表是數據收集,一年組例如11年,主題例如英語,教學組和一個子組。

數據的採集,年和主題都必須選擇,但教學組和子組可以保留不選(全選),單獨選擇中選出的。

我在哪裏SQL存儲過程的條款是因爲在亞組的許多選項現在巨大。以下是幾個選項,其中沒有選擇子組或者選擇了女孩子組或者選擇了男子子組。除此之外還有很多,但爲了簡潔起見,我限制了我發佈的內容。

我的問題是我可以以任何方式優化此代碼,還是我最簡潔?如果你需要更多的例子,請讓我知道,我會將它們添加到帖子中。

where 

--All 
(@TeachingGroup = 'Select All' AND ([StuYear] = @StuYear) AND ([DataCollection] = @DataCollection) AND ([Name] = @SubjectName) AND @Subgroup='Select All' 
OR 
@TeachingGroup <> 'Select All' AND ([StuYear] = @StuYear) AND ([DataCollection] = @DataCollection) AND ([Name] = @SubjectName) AND ([TeachingGroup] = @TeachingGroup) AND @Subgroup='Select All') 
or 
--Gender Girls 
(@TeachingGroup = 'Select All' AND ([StuYear] = @StuYear) AND ([DataCollection] = @DataCollection) AND ([Name] = @SubjectName) AND Gender = 
case when @Subgroup = 'GenF' then 'F' end) 
OR 
@TeachingGroup <> 'Select All' AND ([StuYear] = @StuYear) AND ([DataCollection] = @DataCollection) AND ([Name] = @SubjectName) AND ([TeachingGroup] = @TeachingGroup) AND Gender = case when @Subgroup = 'GenF' then 'F' end 
or 
--Gender boys 
(@TeachingGroup = 'Select All' AND ([StuYear] = @StuYear) AND ([DataCollection] = @DataCollection) AND ([Name] = @SubjectName) AND Gender = 
case when @Subgroup = 'GenM' then 'M' end) 
OR 
@TeachingGroup <> 'Select All' AND ([StuYear] = @StuYear) AND ([DataCollection] = @DataCollection) AND ([Name] = @SubjectName) AND ([TeachingGroup] = @TeachingGroup) AND Gender = case when @Subgroup = 'GenM' then 'M' end 

回答

1

如果您有更多的條件,您可能需要研究動態SQL,您可以根據提供的內容構建不同的查詢。

而且,這將是相當標準的做法,通過「空」是指「全選」

然而,這是你所擁有的一個簡單的版本:

Where 
    [StuYear] = @StuYear And 
    [DataCollection] = @DataCollection And 
    [Name] = @SubjectName And (
     @TeachingGroup = 'Select All' Or 
     [TeachingGroup] = @TeachingGroup 
    ) And (
     @SubGroup = 'Select All' Or 
     Gender = Case 
       When @SubGroup = 'GenF' Then 'F' 
       When @SubGroup = 'GenM' Then 'M' 
      End 
    ) 

動態SQL例如

Declare 
    @params nvarchar(max) = ' 
@StuYear int, 
@DataCollection varchar(30), 
@SubjectName varchar(30), 
@TeachingGroup varchar(30), 
@SubGroup varchar(30)', --replace with your definitions 
    @sql nvarchar(max) = ' 
Select 
    xxx 
from 
    xxx 
Where 
    [StuYear] = @StuYear And 
    [DataCollection] = @DataCollection And 
    [Name] = @SubjectName' 

If @TeachingGroup != 'Select All' 
    Set @sql += ' And TeachingGroup = @TeachingGroup' 

If @SubGroup != 'Select All' 
    Set @sql += ' And Gender = Right(@SubGroup, 1)' 

Exec sp_executesql @sql, @params, 
    @StuYear, @DataCollection, @SubjectName, @TeachingGroup, @SubGroup 
+0

此答案適合我。我也喜歡它有兩個選項供我試用,所以我將在未來考慮使用動態sql方法,但現在標準結果工作正常。 – Matt

1

我會使用動態SQL。這增加越來越Index Seek因爲所有謂詞使用AND連接的機會(也,執行計劃將存儲開始不像OPTION (RECOMPILE)相同@SqlStatement的第二次執行):

DECLARE @StuYear INT, 
     @DataCollection VARCHAR(100), 
     @SubjectName NVARCHAR(50), 
     @TeachingGroup VARCHAR(100), 
     @Subgroup VARCHAR(3); 

SELECT @StuYear = 2013, 
     @DataCollection = 'Col1', 
     @SubjectName = N'Mark', 
     @TeachingGroup = 'Select All', 
     @Subgroup = 'GenM'; 

DECLARE @SqlStatement NVARCHAR(MAX), @Params NVARCHAR(MAX); 

SET @SqlStatement = N' 
SELECT ... 
FROM ... 
where 1=1 
AND  ([StuYear] = @StuYear) 
AND  ([DataCollection] = @DataCollection) 
AND  ([Name] = @SubjectName) ' + CHAR(13) 
+ CASE 
     WHEN @TeachingGroup <> 'Select All' THEN N'AND  ([TeachingGroup] = @TeachingGroup) ' + CHAR(13) 
     ELSE N'' 
    END 
+ CASE 
     WHEN @Subgroup = 'GenF' THEN N'AND  ([Gender] = ''F'') ' + CHAR(13) 
     WHEN @Subgroup = 'GenM' THEN N'AND  ([Gender] = ''M'') ' + CHAR(13) 
     ELSE N'' 
    END; 

-- PRINT @SqlStatement; 

SET @Params = N'@StuYear INT, @DataCollection VARCHAR(100), @SubjectName NVARCHAR(50)'; 

EXEC sp_executesql 
     @SqlStatement, 
     @Params, 
     @StuYear = @StuYear, 
     @DataCollection = @DataCollection, 
     @SubjectName = @SubjectName; 

注:你應該替換所有變量的數據類型,最大長度(以及必要時的歸類),包括用作sp_executesql中參數的變量(請參閱SET = @Params = ...)。