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 = ...)。