Stuff Function in SQL Server - Dealing with Several Primary Keys [duplicate] - sql

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
SQL group_concat function in SQL Server
I am looking to create a query but somehow I am unable to do so. Can anyone please help me out here?
The original data
ID ReportId Email
1 1 a#a.com
2 2 b#b.com
3 1 c#c.com
4 3 d#d.com
5 3 e#e.com
I want to group by ReportId, but all the email should be comma separated. So the result should be:
ReportId Email
1 a#a.com, c#c.com
2 b#b.com
3 d#d.com, e#e.com
What is the best way to do this?
I am trying the group by clause but if there is any other thing then i am open to implement that also. I really appreciate your time and help on this. Thank you.

try this:
SELECT ReportId, Email =
STUFF((SELECT ', ' + Email
FROM your_table b
WHERE b.ReportId = a.ReportId
FOR XML PATH('')), 1, 2, '')
FROM your_table a
GROUP BY ReportId
SQL fiddle demo

SELECT [ReportId],
SUBSTRING(d.EmailList,1, LEN(d.EmailList) - 1) EmailList
FROM
(
SELECT DISTINCT [ReportId]
FROM Table1
) a
CROSS APPLY
(
SELECT [Email] + ', '
FROM Table1 AS B
WHERE A.[ReportId] = B.[ReportId]
FOR XML PATH('')
) D (EmailList)
SQLFiddle Demo

Related

How to Condense SQL Rows Using Stuff?

I have a table of data that looks like:
#test
RecordID
Name
hasSpanishVersion
Type
TypeID
1
Test One
Yes
FormType1
1
1
Test One
Yes
FormType2
2
3
Test Three
No
null
null
4
Test Four
Yes
FormType3
3
5
Test Five
Yes
FormType3
3
I also have another table that looks like:
#formTypes
TypeID
FormType
1
FormType1
2
FormType2
3
FormType3
What I am trying to do is condense the Type column where there are like-RecordIDs / Names. If "hasSpanishVersion" is null, the following two columns will also be null.
I am wanting the example table to look like:
RecordID
Name
hasSpanishVersion
Type
1
Test One
Yes
FormType1, FormType2
3
Test Three
null
null
4
Test Four
Yes
FormType3
5
Test Five
Yes
FormType3
I have tried the following code, but this only takes all of the FormTypes and condenses them for each of the three different types:
SELECT
*,
STUFF((SELECT '; ' + t.formTypeSpanish
FROM #test t
WHERE t.TypeID = ft.TypeID
FOR XML PATH('')), 1, 1, '') as FormTypes
FROM #formTypes ft
GROUP BY ft.TypeID, ft.FormType
ORDER BY 1
You might let your grouping column put in Where in a correlated subquery that and you concatenate value in SELECT
SELECT
RecordID, Name,hasSpanishVersion,
STUFF((SELECT ',' + tt.[Type]
FROM formTypes tt
WHERE
tt.RecordID = t1.RecordID AND
tt.Name = t1.Name AND
tt.hasSpanishVersion = t1.hasSpanishVersion
FOR XML PATH('')), 1, 1, '') as FormTypes
FROM formTypes t1
GROUP BY RecordID, Name,hasSpanishVersion
ORDER BY 1
if your sql-server support STRING_AGG there is another simple way to do that.
SELECT RecordID, Name,hasSpanishVersion,STRING_AGG([Type] ,',')
FROM formTypes
GROUP BY RecordID, Name,hasSpanishVersion
sqlfiddle

Combining values into a single column if more than 1 matches the criteria [duplicate]

This question already has answers here:
Simulating group_concat MySQL function in Microsoft SQL Server 2005?
(12 answers)
Closed 4 years ago.
I am trying to write a query to return the users, some info about them and which security group they're assigned to. Some users have more than one group however, so I instead of returning 2 rows, I would like to combine the security group names.
SELECT ur.loginname
,ur.firstname
,ur.lastname
,sg.securitygroupname
,jt.description
FROM users ur
,usersecuritygroup us
,securitygroup sg
,jobtitle jt
WHERE ur.doctorfacilityid = us.doctorfacilityid
AND us.securitygroupid = sg.securitygroupid
AND ur.jobtitle = jt.jtid
So instead of getting 2 rows like this:
jdoe john doe group1 xyz
jdoe john doe group2 xyz
I would like to return 1 row like this:
jdoe john doe group1, group2 xyz
The security group would be the only column that would have more than one row to meet the criteria (if that matters).
You can put your query into a CTE and use XML to concatenate the values in securitygroupname column or if you are using SQL Server 2017 you can use STRING_AGG() function.
with cte as (
SELECT ur.loginname
,ur.firstname
,ur.lastname
,sg.securitygroupname
,jt.description
FROM users ur
,usersecuritygroup us
,securitygroup sg
,jobtitle jt
WHERE ur.doctorfacilityid = us.doctorfacilityid
AND us.securitygroupid = sg.securitygroupid
AND ur.jobtitle = jt.jtid
)
-- OLD VERSIONS
select distinct
loginname
,firstname
,lastname
,STUFF(
(SELECT
N', ' + securitygroupname
FROM cte c
WHERE loginname = c.loginname
and firstname = c.firstname
and lastname = c.lastname
and description = c.description
FOR XML PATH(''), type).value('text()[1]', 'nvarchar(max)'), 1, 2, N''
) securitygroupname
,description
from cte
-- STARTING SQL SERVER 2017
select
loginname
,firstname
,lastname
,STRING_AGG(securitygroupname, ',') as securitygroupname
,description
from cte
group by loginname, firstname, lastname, description

Combining Data From Multiple Rows

I have 3 tables I am writing a query for: Memos, Memos_Description, Policies. The database was not designed by myself and I cannot change it, this is simply a report.
I currently have a query that seems to be working, but is extremely inefficient before joining the extra tables that I need.
SELECT
Main.CLIENTSNAME,
Main.ENTRYDATE,
Main.AUTHOR,
Main.POLICYNUMBER,
Main.CLIENTS_ID,
Main.MEMOS_ID,
Left(Main.DESCRIPTION,Len(Main.DESCRIPTION)) AS REGARDING
FROM
(
SELECT distinct ST1.MEMOS_ID,
(
SELECT ST2.DESCRIPTION + ' ' AS [text()]
FROM dbo.MEMOS_DESCRIPTION ST2
WHERE ST1.MEMOS_ID = ST2.MEMOS_ID
ORDER BY ST1.MEMOS_ID
For XML PATH ('')
) [DESCRIPTION],
ST1.CLIENTSNAME,
ST1.ENTRYDATE,
ST1.AUTHOR,
ST1.POLICYNUMBER,
ST1.REGARDING,
ST1.CLIENTS_ID
FROM dbo.MEMOS ST1
) [Main]
The tables look like this:
tbl.MEMOS
MEMOS_ID
POLICIES_ID
CLIENTSNAME
tbl.MEMOS_DESCRIPTION
MEMOS_ID
DESCRIPTION
tbl.POLICIES
POLICIES_ID
POLICYNUMBER
The data looks like this:
tbl1.MEMOS_ID | tbl1.CLIENTSNAME
1 PERSON ONE
2 PERSON TWO
3 PERSON THREE
tbl2.MEMOS_ID | tbl2.DESCRIPTION
1 This is a sentence
1 that can run over more
1 than one description record.
2 Person two has
2 something different.
3 Client Created.
tbl3.POLICIES_ID | tbl3.POLICYNUMBER
123 ABCDE
456 FGHIJ
I would like the report to look like:
tbl1.MEMOS_ID | tbl1.CLIENTSNAME | tbl2.DESCRIPTION | tbl3.POLICIES_ID | tbl3.POLICYNUMBER
1 PERSON ONE This is a sentence that can run over more tan one description record. 123 ABCDE
I hope this makes sense and thank you.
Updated Query as per Gordon's suggested answer:
SELECT ST1.*,
STUFF(
(SELECT ' ' + ST2.DESCRIPTION AS [text()]
FROM dbo.MEMOS_DESCRIPTION ST2
WHERE ST1.MEMOS_ID = ST2.MEMOS_ID
ORDER BY ST1.MEMOS_ID
For XML PATH ('')
), 1, 1, '') [REGARDING]
FROM
(SELECT DISTINCT ST1.MEMOS_ID,
ST1.CLIENTSNAME,
ST1.ENTRYDATE,
ST1.AUTHOR,
ST1.POLICYNUMBER,
ST1.CLIENTS_ID,
ST1.POLICIES_ID
FROM dbo.MEMOS ST1
) ST1
LEFT JOIN POLICIES B
ON ST1.POLICIES_ID = B.POLICIES_ID
WHERE ST1.ENTRYDATE >= DATEADD(month, -2, GETDATE())
AND (B.PROD1 = ('123') OR B.PROD1 = ('456') OR B.PROD1 = ('789'))
How does the performance compare if you do the select distinct before doing the string aggregation?
SELECT ST1.*,
STUFF((SELECT ' ' + ST2.DESCRIPTION AS [text()]
FROM dbo.MEMOS_DESCRIPTION ST2
WHERE ST1.MEMOS_ID = ST2.MEMOS_ID
ORDER BY ST1.MEMOS_ID
For XML PATH ('')
), 1, 1, '') ) [DESCRIPTION]
FROM (SELECT DISTINCT T1.MEMOS_ID, ST1.CLIENTSNAME, ST1.ENTRYDATE,
ST1.AUTHOR, ST1.POLICYNUMBER, ST1.REGARDING, ST1.CLIENTS_ID
FROM dbo.MEMOS ST1
) ST1
I suspect that SQL Server might be doing the string aggregation for every row before running distinct -- and that is a lot of unnecessary work.

How to join all data in table for one column as string with sql?

I want to join all data in table. For example: I have a table like this,
ID Name ForeingId
----------------------
1 A 1
2 B 1
3 C 2
4 D 1
5 E 1
I want to get as a result the following with query. Such as 'SELECT ... WHERE ForeingId=1' .
I dont want to use procedure or function.
result : A,B,D,E
For ORACLE, try this:
SELECT
LISTAGG(name, ',') WITHIN GROUP (ORDER BY name) AS NAME
FROM TABLE
WHERE ForeingId= '1'
I am using MSSQL
I thank everyone for the answers. I found answer with link of #mehul9595's comment.
Simulating group_concat MySQL function in Microsoft SQL Server 2005?
This way:
SELECT STUFF(
(SELECT ',' + t.name FROM table_name t
where t.foreingId = 1 FOR XML PATH ('')), 1, 1, '')

SQL Server 2005 pivot table

I want to pivot a column in SQL Server 2005. I'm pretty sure there is XML way to get it done but can't figure it out. Here is a table:
ID Class
1 20002
1 20003
1 20004
2 20003
2 20012
Desired value is:
ID Class
1 20002,20003,20004
2 20003,20012
Thanks in advance
I am not sure PIVOT (or UNPIVOT) are what you are looking for. Below is some code that I use when I need to get a CSV list embedded in a query. Hope it helps!
SELECT DISTINCT
ID
, Class = STUFF(
cast(
(select ', ' + cast(Class as nvarchar)
from TableName t2
WHERE t2.ID = t1.ID
for xml path('')) as nvarchar(2000))
,1,2, N'')
FROM TableName t1