2010-09-29 121 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中带有特殊字符的大多数常见问题。