SQL-запрос для комплексной фильтрации

#sql #sql-server

#sql #sql-сервер

Вопрос:

У меня есть схема SQL примерно так.

 select Id, AccountId, GradeLevelStart, GradeLevelEnd from AccountProfile
 

Который содержит данные, как показано на этом снимке.

введите описание изображения здесь

Здесь GradeLevelStart, а GradeLevelEnd — идентификатор Gradelevels. смотрите ниже запрос и его данные.

 select Id, Name, Abbreviation from GradeLevel
 

введите описание изображения здесь

Я создал один фильтр, который работает с использованием оператора between.
Поток — это что-то вроде этого,

  • пользователь выбирает 1-й, 2-й класс, и этот запрос вернет все учетные записи, которые находятся между ними для этого класса, и это GradeLevelStart, GradeLevelEnd.

Вот запрос к нему.

 DECLARE @Grades NVARCHAR(100)
SET @Grades = '3'

    select AccountId, GradeLevelStart, GradeLevelEnd, glStart.Name, glStart.Abbreviation, glEnd.Name, glEnd.Abbreviation 
    from AccountProfile 
        left join GradeLevel glStart on glStart.ID = GradeLevelStart
        left join GradeLevel glEnd on glEnd.ID = GradeLevelEnd
    where @Grades IS NULL OR @Grades BETWEEN GradeLevelStart and GradeLevelEnd
 

Что я ищу?

До сих пор все это работает нормально, но для фильтрации еще не требуется несколько @Grades .

Итак, я хочу, чтобы пользователь вводил данные в формате, подобном приведенному ниже запросу, и система должна возвращать все учетные записи, у которых есть GradeLevelStart и GradeLevelEnd между этим @Grades

 SET @Grades = '3,13,'
 

Что я пробовал до сих пор?

  • Я создал временную таблицу и попытался использовать join, но безуспешно, поскольку я не знаю, как использовать там оператор between.
  • Я также использовал STRING_SPLIT, но это бесполезно.

Любая помощь была бы очень признательна.

Ответ №1:

Для достижения этой цели используйте функцию разделения строк:

 DECLARE @Grades NVARCHAR(100)
SET @Grades = '3,13'

select AccountId, GradeLevelStart, GradeLevelEnd, glStart.Name, glStart.Abbreviation, 
glEnd.Name, glEnd.Abbreviation 
from AccountProfile 
left join GradeLevel glStart on glStart.ID = GradeLevelStart
left join GradeLevel glEnd on glEnd.ID = GradeLevelEnd
OUTER APPLY STRING_SPLIT(@Grades,',') s
where @Grades IS NULL OR (s.value) BETWEEN GradeLevelStart and GradeLevelEnd
 

Кроме того, вы можете добиться того же, используя узлы XML вместо РАЗДЕЛЕНИЯ СТРОК:

Для вашей ссылки:

 declare @S varchar(100) = 'Hello John Smith'

select 
n.r.value('.', 'varchar(50)')
from (select cast('<r>' replace(@S, ' ', '</r><r>') '</r>' as xml)) as s(XMLCol)
cross apply s.XMLCol.nodes('r') as n(r)
 

Комментарии:

1. похоже, что внешнее применение будет работать. но я все еще ищу наилучшую практику. дайте мне знать, если есть какой-либо другой способ.