Как я должен изменить этот оператор SQL? - PullRequest
4 голосов
/ 29 сентября 2010

My SQL Server view

SELECT     
   geo.HyperLinks.CatID, geo.Tags.Tag, geo.HyperLinks.HyperLinksID
FROM
   geo.HyperLinks LEFT OUTER JOIN
       geo.Tags INNER JOIN
       geo.TagsList ON geo.Tags.TagID = geo.TagsList.TagID ON geo.HyperLinks.HyperLinksID = geo.TagsList.HyperLinksID WHERE HyperLinksID = 1

возвращает эти ...

HyperLinksID CatID Tags
1            2     Sport
1            2     Tennis
1            2     Golf

Как мне изменить вышеуказанное, чтобы получить такие результаты, как

HyperLinksID CatID TagsInOneRowSeperatedWithSpaceCharacter
1            2     Sport Tennis Golf

ОБНОВЛЕНИЕ: Как предложил Брэд, я пришел сюда ...

DECLARE @TagList varchar(100)
SELECT @TagList = COALESCE(@TagList + ', ', '') + CAST(TagID AS nvarchar(100))
FROM TagsList
WHERE HyperLinksID = 1
SELECT @TagList

Теперь результат выглядит как

HyperLinksID CatID TagsInOneRowSeperatedWithSpaceCharacter
1            2     ID_OF_Sport ID_OF_Tennis ID_OF_Golf

И, конечно, мне нужно объединить содержимое из переменной @TagList и оригинал SELECT оператор ...

Что означает, что мне придется ждать святой ТАКОЙ щедрости: (

Ответы [ 3 ]

11 голосов
/ 29 сентября 2010

Если SQL, попробуйте этот пост:

Объединение значений строк

Если вы хотите попробовать свои силы в коде CLR, есть примеры создания пользовательского агрегатафункция конкатенации, опять же, для MS SQL.

Этот пост довольно исчерпывающий, с множеством способов достичь вашей цели.

4 голосов
/ 01 октября 2010

Используя подход отсюда , чтобы избежать каких-либо проблем, если ваши имена тегов содержат специальные символы XML:.

;With HyperLinks As
(
SELECT 1 AS HyperLinksID, 2 AS CatID
),
TagsList AS
(
SELECT 1 AS TagId, 1 AS HyperLinksID UNION ALL
SELECT 2 AS TagId, 1 AS HyperLinksID UNION ALL
SELECT 3 AS TagId, 1 AS HyperLinksID
)
,
Tags AS
(
SELECT 1 AS TagId, 'Sport' as Tag UNION ALL
SELECT 2 AS TagId, 'Tennis' as Tag UNION ALL
SELECT 3 AS TagId, 'Golf' as Tag 
)
SELECT HyperLinksID,
       CatID       ,
      (SELECT mydata
       FROM    ( SELECT Tag AS [data()]
               FROM    Tags t
                       JOIN TagsList tl
                       ON      t.TagId = tl.TagId
               WHERE   tl.HyperLinksID = h.HyperLinksID 
               ORDER BY t.TagId 
               FOR XML PATH(''), TYPE
               ) AS d ( mydata ) FOR XML RAW,
               TYPE
       )
       .value( '/row[1]/mydata[1]', 'varchar(max)' ) TagsInOneRowSeperatedWithSpaceCharacter
FROM   HyperLinks h

Редактировать: Как указывает КМ вкомментарии этот метод фактически автоматически добавляет пробелы, поэтому я удалил добавленные вручную пробелы.Для разделителей, отличных от пробелов, таких как запятые ответ Питера кажется более подходящим.

Если вы знаете, что ваши данные не будут содержать проблемных символов, то более простая (вероятно, более производительная) версия -

SELECT CatID       ,
       HyperLinksID,
       stuff(
       ( SELECT ' ' + Tag 
               FROM    Tags t
                       JOIN TagsList tl
                       ON      t.TagId = tl.TagId
               WHERE   tl.HyperLinksID = h.HyperLinksID 
               ORDER BY t.TagId 
               FOR XML PATH('')
       ), 1, 1, '') TagsInOneRowSeperatedWithSpaceCharacter
FROM   HyperLinks h
2 голосов
/ 01 октября 2010

Используйте FOR XML в коррелированном подзапросе. Для списка, разделенного пробелами:

SELECT h.HyperLinksID, h.CatID
, TagList = (
    SELECT t.Tag AS [data()]
    FROM geo.TagList l
    JOIN geo.Tags t ON l.TagId = t.TagId
    WHERE l.HyperLinksID = h.HyperLinksID
    ORDER BY t.Tag
    FOR XML PATH(''), TYPE
  ).value('.','NVARCHAR(MAX)')
FROM geo.HyperLinks AS h
WHERE h.HyperLinksID = 1

Для любого другого разделителя:

SELECT h.HyperLinksID, h.CatID
, TagList = STUFF((
      SELECT ', '+t.Tag
      FROM geo.TagList l
      JOIN geo.Tags t ON l.TagId = t.TagId
      WHERE l.HyperLinksID = h.HyperLinksID
      ORDER BY t.Tag
      FOR XML PATH(''), TYPE
    ).value('.','NVARCHAR(MAX)')
  ,1,2,'')
FROM geo.HyperLinks AS h
WHERE h.HyperLinksID = 1

Подзапрос создает список с разделителями, а затем STUFF(...,1,2,'') удаляет ведущий ,. TYPE).value() обходит большинство распространенных проблем с помощью специальных символов в XML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...