2

В asp Я установил несколько выпадающих меню, которые позволяют пользователю фильтровать данные, отображаемые на странице, в зависимости от их выбора.SQL оптимизирует условия в том, где статья

Эти выпадающие списки предназначены для сбора данных, год группы, например, год 11, предмет, например английский, обучающая группа и подгруппа.

Необходимо выбрать набор данных, год и предмет, но обучающая группа и подгруппа могут оставаться невыбранными (выберите все), выбранными индивидуально или оба выбранными.

Мое предложение where в хранимой процедуре 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, где вы строите различные запросы в зависимости от того, что поставляется.

Кроме того, было бы довольно стандартная практика, чтобы пройти «Null» означает «Select All»

Однако, это более простой вариант того, что у вас есть:

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 (также планы выполнения будут сохранены начиная второй выполнение одного и того же @SqlStatement в отличие от OPTION (RECOMPILE)):

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

Смежные вопросы