问题
I want to concatenate multiple rows in one column. I found many examples in Internet but does not working for me. What am I doing wrong?
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
I'm still having the information like this
UserID Email
1 abc@yahoo.com
1 cde@gmail.com
--EDIT--
Ok, I did this change but still having 2 rows. If I apply distinct this will fix my problem but why do I have to use distinct. The query must group it by itself.
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
Results
UserID Email
1 abc@yahoo.com; cde@gmail.com
1 abc@yahoo.com; cde@gmail.com
回答1:
Unfortunately, SQL Server doesn't have proper string concatenation, so you cannot concatenate strings while grouping. So there're several possible solutions.
1. If you want to concatenate data for single ID, you can use variable trick:
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. If you want to do proper grouping, you can use xml trick. So, basic idea is - you get distinct UserID as anchor query (using group by
), and then concatenate data in the subquery. Important thing is to do this correctly, use for xml ... type
and get concatenated string as .value()
, so special characters will be treated correctly:
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
See sql fiddle demo with examples: sql fiddle demo
回答2:
The entire sub query inside the STUFF() function is evaluated for each row that meets the criteria in the where clause.
In this case you seem to have two rows with ID of 1.
Since the results you want are for the entire set, each row in that set will have the same results, so selecting distinct just helps you hide the duplicates.
If you format your query like this, it will be easier to see why this happens:
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
来源:https://stackoverflow.com/questions/20057655/multiple-rows-in-one-column-sql-server