SQL Server中的一列中有多行

时间:2013-11-18 20:52:26

标签: sql-server xml path concatenation sqlxml

我想在一列中连接多行。我在互联网上找到了许多例子,但对我不起作用。我做错了什么?

        SELECT UserID,  
        STUFF((SELECT '; ' + Email.Email From Email where  UserEmail.EmailID = Email.ID for xml path('')),1,1, '') AS Emails
        From UserEmail
        where UserID = 1

我仍然有这样的信息

UserID  Email
1       abc@yahoo.com
1       cde@gmail.com 
  

- 编辑 -

好的,我做了这个改变,但仍然有2行。如果我应用distinct,这将解决我的问题,但为什么我必须使用distinct。查询必须自行分组。

        SELECT UserID,  
        STUFF(( SELECT '; ' + ea.Email 
                From Email ea inner join UserMail ue_inner on ue_inner.EmailID = ea.ID 
                where 
                ue_inner.UserID = ue.UserID
                for xml path('')), 1, 1, '') 
                AS Email
        From UserEmail ue
        where UserID = 1

结果

UserID   Email 
1        abc@yahoo.com; cde@gmail.com
1        abc@yahoo.com; cde@gmail.com

2 个答案:

答案 0 :(得分:5)

不幸的是,SQL Server没有正确的字符串连接,因此在分组时无法连接字符串。所以有几种可能的解决方案。

1。如果要连接单个ID的数据,可以使用变量技巧

declare @Emails varchar(max)

select @Emails = isnull(@Emails + ', ', '') + E.Email
from Email as E
    inner join UserEmail as UE on UE.EmailID = E.EmailID
where UE.UserID = 1

select @Emails;

-----------------
abc@yahoo.com, cde@gmail.com

2. 如果您想进行正确的分组,可以使用 xml技巧。因此,基本思路是 - 您将不同的UserID作为锚点查询(使用group by),然后在子查询中连接数据。重要的是要正确执行此操作,使用for xml ... type并将连接字符串设置为.value(),以便正确处理特殊字符:

select
    UE.UserID,
    stuff(
        (
            select ', ' + TE.Email
            from Email as TE
                inner join UserEmail as TUE on TUE.EmailID = TE.EmailID
            where TUE.UserID = UE.UserID
            for xml path(''), type
        ).value('.', 'varchar(max)')
    , 1, 2, '') as Emails
from UserEmail as UE
group by UE.UserID

使用示例查看sql小提琴演示: 的 sql fiddle demo

答案 1 :(得分:2)

对于满足where子句中条件的每一行,将评估STUFF()函数内的整个子查询。

在这种情况下,您似乎有两行ID为1。

由于您想要的结果是针对整个集合的,因此该集合中的每一行都会有相同的结果,因此选择distinct只会帮助您隐藏重复项。

如果您像这样格式化查询,则会更容易理解为什么会发生这种情况:

SELECT 
    UserID,  
    STUFF(( SELECT '; ' + ea.Email 
            From Email ea inner join UserMail ue_inner on ue_inner.EmailID = ea.ID 
            where 
            ue_inner.UserID = ue.UserID
            for xml path('')), 1, 1, '') AS Email,
    ue.Email
From UserEmail ue
where UserID = 1