Это распространенный вопрос, который часто задают несколькими различными способами (объединять строки в строку, объединять строки в строку, объединять строки в строку, объединять строки в строку и т. Д.).Существует два общепринятых способа обработки произвольного количества строк в одной строке в SQL Server.
Первым и, как правило, самым простым является злоупотребление Путь XML в сочетании с функцией STUFF следующим образом:
select rsQuestions.QuestionID,
stuff((select ', '+ rsTags.TagName
from @Tags rsTags
inner join @QuestionTags rsMap on rsMap.TagID = rsTags.TagID
where rsMap.QuestionID = rsQuestions.QuestionID
for xml path(''), type).value('.', 'nvarchar(max)'), 1, 1, '')
from @QuestionRevisions rsQuestions
Вот рабочий пример (заимствуя немного измененную настройку из Mack).Для ваших целей вы можете сохранить результаты этого запроса в общем табличном выражении или в подзапросе (я оставлю это в качестве упражнения).
Второй метод - использовать рекурсивный общийтабличное выражение .Вот аннотированный пример того, как это будет работать:
--NumberedTags establishes a ranked list of tags for each question.
--The key here is using row_number() or rank() partitioned by the particular question
;with NumberedTags (QuestionID, TagString, TagNum) as
(
select QuestionID,
cast(TagName as nvarchar(max)) as TagString,
row_number() over (partition by QuestionID order by rsTags.TagID) as TagNum
from @QuestionTags rsMap
inner join @Tags rsTags on rsTags.TagID = rsMap.TagID
),
--TagsAsString is the recursive query
TagsAsString (QuestionID, TagString, TagNum) as
(
--The first query in the common table expression establishes the anchor for the
--recursive query, in this case selecting the first tag for each question
select QuestionID,
TagString,
TagNum
from NumberedTags
where TagNum = 1
union all
--The second query in the union performs the recursion by joining the
--anchor to the next tag, and so on...
select NumberedTags.QuestionID,
TagsAsString.TagString + ', ' + NumberedTags.TagString,
NumberedTags.TagNum
from NumberedTags
inner join TagsAsString on TagsAsString.QuestionID = NumberedTags.QuestionID
and NumberedTags.TagNum = TagsAsString.TagNum + 1
)
--The result of the recursive query is a list of tag strings building up to the final
--string, of which we only want the last, so here we select the longest one which
--gives us the final result
select QuestionID, max(TagString)
from TagsAsString
group by QuestionID
А вот рабочая версия .Опять же, вы можете использовать результаты в общем табличном выражении или подзапросе, чтобы объединиться с другими таблицами, чтобы получить конечный результат.Надеемся, что аннотации помогут вам лучше понять, как работает рекурсивное общее табличное выражение (хотя ссылка в ответе Macks также подробно описывает метод).
Конечно, есть и другой способ сделать это., который не обрабатывает произвольное количество строк, то есть объединяет вашу таблицу с псевдонимом несколько раз, что вы и сделали в своем ответе.