Хорошо, я чувствую, что мне нужно перейти к комментарию о Как объединить несколько строк в один столбец в SQL Server? и предоставить более предпочтительный ответ.
Мне очень жаль, но использование таких скалярных функций снизит производительность. Просто откройте SQL Profiler и посмотрите, что происходит, когда вы используете скалярную функцию, которая вызывает таблицу.
Кроме того, метод «обновить переменную» для конкатенации не рекомендуется, так как эта функция может не сохраняться в будущих версиях.
Предпочтительный способ объединения строк вместо FOR FOR PATH.
select
stuff((select ', ' + t.tag from tags t where t.photoid = p.photoid order by tag for xml path('')),1,2,'') as taglist
,*
from photos
order by photoid;
В качестве примеров того, как работает FOR XML PATH, рассмотрите следующее, представив, что у вас есть таблица с двумя полями с именами 'id' и 'name'
SELECT id, name
FROM table
order by name
FOR XML PATH('item'),root('itemlist')
;
Дает:
<itemlist><item><id>2</id><name>Aardvark</a></item><item><id>1</id><name>Zebra</name></item></itemlist>
Но если вы пропустите ROOT, вы получите что-то немного другое:
SELECT id, name
FROM table
order by name
FOR XML PATH('item')
;
<item><id>2</id><name>Aardvark</a></item><item><id>1</id><name>Zebra</name></item>
И если вы поместите пустую строку PATH, вы станете еще ближе к обычной конкатенации строк:
SELECT id, name
FROM table
order by name
FOR XML PATH('')
;
<id>2</id><name>Aardvark</a><id>1</id><name>Zebra</name>
Теперь наступает очень сложный момент ... Если вы называете столбец, начинающийся со знака @, он становится атрибутом, а если столбец не имеет имени (или вы называете его [*]), то он пропускает и этот тег:
SELECT ',' + name
FROM table
order by name
FOR XML PATH('')
;
,Aardvark,Zebra
Теперь, наконец, чтобы убрать начальную запятую, приходит команда STUFF. STUFF (s, x, n, s2) извлекает n символов s, начиная с позиции x. На их место ставится s2. Итак:
SELECT STUFF ('abcde', 2,3, '123456');
дает:
a123456e
Итак, взгляните на мой запрос выше для вашего списка тегов.
select
stuff((select ', ' + t.tag from tags t where t.photoid = p.photoid order by tag for xml path('')),1,2,'') as taglist
,*
from photos
order by photoid;
Для каждой фотографии у меня есть подзапрос, который захватывает теги и объединяет их (по порядку) с запятой и пробелом. Затем я окружаю этот подзапрос командой stuff, чтобы убрать начальную запятую и пробел.
Я прошу прощения за любые опечатки - на самом деле я не создал таблицы на своей машине, чтобы проверить это.
Rob