【问题标题】:Multiple rows in one column SQL Server一列中的多行 SQL Server
【发布时间】:2013-11-18 20:52:26
【问题描述】:

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

        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

【问题讨论】:

    标签: sql-server xml path concatenation sqlxml


    【解决方案1】:

    不幸的是,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技巧。所以,基本的想法是 - 你得到不同的用户 ID 作为锚查询(使用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 fiddle 演示: sql fiddle demo

    【讨论】:

      【解决方案2】:

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

      在这种情况下,您似乎有两行 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-10
        • 2012-05-27
        • 2013-05-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多