2010-09-29 129 views
4

我的SQL Server視圖我應該如何修改這條SQL語句?

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 

UPDATE結果:布拉德建議我來到這裏...

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聲明相結合......

這意味着我」將不得不等待神聖的SO恩惠:(

+1

什麼是數據庫服務器? – 2010-09-29 17:23:40

回答

11

如果SQL,請嘗試此帖:

Concatenating Row Values

如果您想嘗試一下CLR代碼,有一些爲MS SQL創建連接的自定義聚合函數的示例。

This post非常詳盡,有很多方法可以實現您的目標。

+0

+1爲第二個鏈接。 – Giorgi 2010-10-01 18:39:27

4

使用方法from here可以避免任何問題,如果您的標記名稱包含特殊的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 

編輯:作爲KM在評論中指出,這種方法實際上將自動添加空格,所以我已經刪除了手動添加的空間。對於空格以外的分隔符,如逗號Peter's answer似乎更合適。

如果你知道你的數據將不包含任何問題的字符,然後一個簡單的(可能是更好的性能)的版本是

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 
+0

+1 ...並且因爲您在第一個代碼示例中試圖避開我:P – Gage 2010-10-01 18:34:24

+0

(它試圖避免展開xml控制字符),因此在「TagsInOneRowSeperatedWithSpaceCharacter」列中總是會有兩個空格跟隨值。一個空間似乎是自動的,另一個是手動添加的空間。不好的部分是自動空間位於值和手動空間之間。嘗試一下,嘗試從你的第一個查詢中得到這個值'Sport,Tennis,Golf'。你會得到'運動,網球,高爾夫'。 – 2010-10-20 14:42:19

+0

@KM - 非常感謝您讓我知道。我會稍微看一下。 – 2010-10-20 14:45:04

2

使用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中帶有特殊字符的大多數常見問題。