我想在一列中连接多行。我在互联网上找到了许多例子,但对我不起作用。我做错了什么?
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
答案 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