#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. похоже, что внешнее применение будет работать. но я все еще ищу наилучшую практику. дайте мне знать, если есть какой-либо другой способ.