sql server comma delimted string values into one row - sql

I have a query that returns a row of multiple Itemcodes. The result is
Date group list of item code
2015-04-15 118 FYCT-00063,FYCM-00016,FYCM-00064,FYCF-00018
it's working fine but i need the result like this, with quotes around every code 'FYCT-00063','FYCM-00016','FYCM-00064','FYCF-00018'
The query is this:
SELECT DISTINCT SS.PostDate,SS.U_Unit,STUFF((
SELECT ', ',+ CAST(OWOR.ItemCode AS VARCHAR(10)) [text()]
FROM OWOR
WHERE OWOR.PostDate=SS.PostDate AND OWOR.U_Unit=SS.U_Unit AND OWOR.Status=SS.Status
FOR XML PATH('') , TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') LISTGroup
from owor SS
Where SS.PostDate='15.APRIL.15' AND SS.U_Unit='Unit No 2' and SS.Status!='C'

SELECT DISTINCT SS.PostDate,SS.U_Unit,
STUFF((
SELECT ', ',+ '''' + CAST(OWOR.ItemCode AS VARCHAR(10) + '''') [text()]
FROM OWOR
WHERE OWOR.PostDate=SS.PostDate
AND OWOR.U_Unit=SS.U_Unit
AND OWOR.Status=SS.Status
FOR XML PATH('') , TYPE) .value('.','NVARCHAR(MAX)'),1,2,' ') LISTGroup
FROM owor SS
WHERE SS.PostDate='15.APRIL.15'
AND SS.U_Unit='Unit No 2'
AND SS.Status!='C'

Try this
SELECT DISTINCT SS.PostDate
,SS.U_Unit
,STUFF((
SELECT ', '
+ QUOTENAME(CAST(OWOR.ItemCode AS VARCHAR(10), ''''))
FROM OWOR
WHERE OWOR.PostDate = SS.PostDate
AND OWOR.U_Unit = SS.U_Unit
AND OWOR.STATUS = SS.STATUS
FOR XML PATH('')
).value('.', 'NVARCHAR(MAX)'), 1, 2, ' ') LISTGroup
FROM owor SS
WHERE SS.PostDate = '15.APRIL.15'
AND SS.U_Unit = 'Unit No 2'
AND SS.STATUS != 'C'

Try like this:
DECLARE #STRING varchar(max)
SELECT #STRING = 'FYCT-00063,FYCM-00016,FYCM-00064,FYCF-00018'
SELECT '''' + REPLACE(#STRING,',',''',''') + ''''
SQLFIDDLE DEMO
In your case it would be like
select distinct SS.PostDate,SS.U_Unit,'''' + REPLACE(STUFF((
SELECT ', ',+ CAST(OWOR.ItemCode AS VARCHAR(10)) [text()]
FROM OWOR
where OWOR.PostDate=SS.PostDate AND OWOR.U_Unit=SS.U_Unit AND OWOR.Status=SS.Status
FOR XML PATH('') , TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' '),',',''',''') + '''' LISTGroup
from owor SS
Where SS.PostDate='15.APRIL.15' AND SS.U_Unit='Unit No 2' and SS.Status!='C'

Related

Merge column value based on another column value - TSQL

I m using the below query to merge column Message based on column 'Customer_Name' from table Customers
SELECT
[Customer_Name],
STUFF((SELECT
', ' + LTRIM(RTRIM([Message]))
FROM [dbo].[Customers] t2
WHERE t2.[Customer_Name] = t1.[Customer_Name]
FOR XML PATH ('')), 1, 1, '')
FROM [dbo].[Customers] t1
GROUP BY [Customer_Name]
Using the above code, the Message are separated by , but i want a new line. i try to use CHAR(13)+CHAR(10) but i getting #x0D; and the merge column seems to be wrong.
Any idea on how to fix it will greatly appreciate.
Answer using #Larnu help and posts on comments
SELECT
[Customer_Name],
STUFF((SELECT
(CHAR(13) + CHAR(10)) + LTRIM(RTRIM([Message]))
FROM [Customers] t2
WHERE t2.[Customer_Name] = t1.[Customer_Name]
FOR XML PATH (''),TYPE
).value('(./text())[1]','varchar(MAX)'),1,2,'')
FROM [Customers] t1
GROUP BY [Customer_Name]
Your solution use xml serialization .
#x0D; is xml serialization of char(13)
If you use at least SQL Server 2017 you can use STRING_AGG function
SELECT
[Customer_Name],
STRING_AGG([Message],', ') as [Messages]
FROM [dbo].[Customers] t1
GROUP BY [Customer_Name]
otherwise you can add replace.
SELECT
[Customer_Name],
REPLACE(
STUFF((SELECT
', ' + LTRIM(RTRIM([Message]))
FROM [dbo].[Customers] t2
WHERE t2.[Customer_Name] = t1.[Customer_Name]
FOR XML PATH ('')), 1, 2, ''),
'#x0D;',
CHAR(13)) as [Messages]
FROM [dbo].[Customers] t1
GROUP BY [Customer_Name]
The correct method to prevent XML entitization is actually to generate it as the xml data type using the TYPE option, then pull it back out with .value
DECLARE #sep NVARCHAR(10) = ', '; -- or you can use CHAR(13)+CHAR(10)
SELECT
[Customer_Name],
STUFF(
(SELECT #sep + LTRIM(RTRIM([Message]))
FROM [dbo].[Customers] t2
WHERE t2.[Customer_Name] = t1.[Customer_Name]
FOR XML PATH (''), TYPE
).value('text()[1]','nvarchar(max)'), 1, LEN(#sep), '')
FROM [dbo].[Customers] t1
GROUP BY [Customer_Name]

Query database to grab data per unique id

I have a database table with the following information (Don't mind the CreatedDates not matching, this is a testing database table):
I want to be able to create a query to Intents and the respective Transcript based on the ContactId (which there are multiple for one user).
As of right now I was able to accomplish pulling out the Intents by user (distinct) with the following:
SELECT distinct [ContactId],[Intents] =
STUFF((SELECT ' ,' + LTRIM(RTRIM(Intent))
FROM ACCOUNT_DATA b
WHERE b.ContactId = a.ContactId
FOR XML PATH('')), 1, 2, '')
FROM ACCOUNT_DATA a
GROUP BY ContactId;
My desired output would be something like this:
Query => Select all users from the Database (distinct) and return Intents (Distinct) + Transcript data and count of the intents. So like:
d463d996-78cc-428e-8a76-e4875e1c8ff4
RescheudleApt (4) : Reschuedle Appointment, Ok, what date?, Ok, what date?,Ok, what date?
ConfirmAppt (2): Confirm my appointment, ok your appointment has been confirmed
So on and so forth for each ContactId in the table, how would I go about this and am I on the right track?
I know that this would be formatted in different alias tables such as ContactId, Count, Transcript.
Try changing your query like this:
SELECT
ContactId,
Intent + ' (' + CONVERT(VARCHAR,COUNT(Intent)) + ')' as Intents,
[Transcript] = STUFF((SELECT ' ,' + LTRIM(RTRIM(b.Transcript))
FROM ACCOUNT_DATA b
WHERE b.ContactId = a.ContactId
AND b.Intent = a.Intent
FOR XML PATH('')), 1, 2, '')
FROM
ACCOUNT_DATA a
GROUP BY
ContactId, Intent
ORDER BY
ContactId
Here's a demo
or if you want to concatenate Intent and Transcript
SELECT
ContactId,
Intent + ' (' + CONVERT(VARCHAR,COUNT(Intent)) + ') : ' +
STUFF((SELECT ' ,' + LTRIM(RTRIM(b.Transcript))
FROM ACCOUNT_DATA b
WHERE b.ContactId = a.ContactId
AND b.Intent = a.Intent
FOR XML PATH('')), 1, 2, '') AS "Intent + Transcript"
FROM
ACCOUNT_DATA a
GROUP BY
ContactId, Intent
ORDER BY
ContactId
Edit: Final Query
SELECT DISTINCT ContactId, [Transcript]=STUFF((SELECT '; ' + IntentTranscript
FROM (
SELECT a.ContactId,
a.Intent + ' (' + CONVERT(VARCHAR,COUNT(a.Intent)) + ') : ' +
STUFF((SELECT ' ,' + LTRIM(RTRIM(b.Transcript))
FROM ACCOUNT_DATA b
WHERE b.ContactId = a.ContactId
AND b.Intent = a.Intent
FOR XML PATH('')), 1, 2, '') AS "IntentTranscript"
FROM ACCOUNT_DATA a
GROUP BY a.ContactId, a.Intent
) c
WHERE c.ContactId = INNER_ACCOUNT_DATA.ContactId
FOR XML PATH('')), 1, 2, '')
FROM
(
SELECT a.ContactId,
a.Intent + ' (' + CONVERT(VARCHAR,COUNT(a.Intent)) + ') : ' +
STUFF((SELECT ' ,' + LTRIM(RTRIM(b.Transcript))
FROM ACCOUNT_DATA b
WHERE b.ContactId = a.ContactId
AND b.Intent = a.Intent
FOR XML PATH('')), 1, 2, '') AS "IntentTranscript"
FROM ACCOUNT_DATA a
GROUP BY a.ContactId, a.Intent
) AS INNER_ACCOUNT_DATA
ORDER BY ContactId
Here's a demo

MSSQL - GROUP_CONCAT

Here is the sample data :
IdProduit Localisation Qte_EnMain
4266864286880063006 E2-R40-B-T 13.00000
4266864286880063006 E2-R45-B-T 81.00000
4266864286880063007 E2-R45-C-T 17.00000
4266864286880063008 E2-R37-B-T 8.00000
And this is what i would like to have
IdProduit AllLocalisation
4266864286880063006 E2-R40-B-T (13), E2-R45-B-T (81)
4266864286880063007 E2-R45-C-T (17)
4266864286880063008 E2-R37-B-T (8)
I watched all the examples of GROUP_CONCAT on the forum and I tried several tests.
I don't really understand STUFF().
Here is what i would like to do :
SELECT
a.IdProduit,
GROUP_CONCAT(
CONCAT(b.Localisation, ' (', CAST(ROUND(a.Qte_EnMain, 0) AS NUMERIC(36, 0)), ')')
) AS AllLocation
FROM
ogasys.INV_InventENTLoc a
LEFT JOIN ogasys.INV_LocName b ON a.IdLoc = b.IdLoc
GROUP BY a.IdProduit, b.Localisation, a.Qte_EnMain
Now because GROUP_CONCAT is nto working with MSSQL this is the query i have created with all example on this forum.
SELECT
DISTINCT
a1.IdProduit,
STUFF((SELECT DISTINCT '' + b2.Localisation
FROM
ogasys.INV_InventENTLoc a2
LEFT JOIN ogasys.INV_LocName b2 ON a2.IdLoc = b2.IdLoc
WHERE a2.IdLoc = a1.IdLoc
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 0, '') data
FROM
ogasys.INV_InventENTLoc a1
LEFT JOIN ogasys.INV_LocName b1 ON a1.IdLoc = b1.IdLoc
ORDER BY a1.IdProduit
The query only return one localisation by row i don't understand how to make this query working.
EDIT:
Here is the solution for my situation :
SELECT
a.IdProduit,
STUFF(
(SELECT ', ' + b2.Localisation + ' (' + CAST(CAST(ROUND(a2.Qte_EnMain, 0) AS NUMERIC(36, 0)) AS VARCHAR(32)) + ')'
FROM ogasys.INV_InventENTLoc a2
LEFT JOIN ogasys.INV_LocName b2 ON a2.IdLoc = b2.IdLoc
WHERE a.IdProduit = a2.IdProduit
FOR XML PATH (''))
, 1, 1, '') AS AllLocalisation
FROM
ogasys.INV_InventENTLoc a
LEFT JOIN ogasys.INV_LocName b ON a.IdLoc = b.IdLoc
GROUP BY a.IdProduit
using STUFF
declare #table table (IdProduit varchar(100), Localisation varchar(50), Qte_EnMain float)
insert into #table
values
('4266864286880063006','E2-R40-B-T', 13.00000),
('4266864286880063006','E2-R45-B-T', 81.00000),
('4266864286880063007','E2-R45-C-T', 17.00000),
('4266864286880063008','E2-R37-B-T', 8.00000)
select IdProduit,
STUFF (
(SELECT
',' + localisation + concat(' (',cast(qte_enMain as varchar(4)),') ')
FROM #table t2
where t2.IdProduit = t1.IdProduit
FOR XML PATH('')), 1, 1, ''
)
from #table t1
group by
IdProduit

many rows into a single column with SQL

I have an one to many table, and if there is rows that have same reference id(Paragraph ID) I want to concatenate so LoginName value have many in same row.
This query does what I want it to do but there is a problem, It replaces first char. the STUFF function requires a replace value.
My question:
How can I do this without replacing first char?
SELECT DISTINCT
ParagraphID
, STUFF((
SELECT N'|' + CAST([LoginName] AS VARCHAR(255))
FROM [dbo].[CM_Signature] f2
WHERE f1.ParagraphID = f2.ParagraphID
FOR XML PATH ('')), 1, 2, '') AS FileNameString
FROM [dbo].[CM_Signature] f1
Expected value:
Daniel | Emma
Here is what you can use:
SELECT DISTINCT
ParagraphID
, STUFF((
SELECT N' | ' + CAST([LoginName] AS VARCHAR(255))
FROM [dbo].[CM_Signature] f2
WHERE f1.ParagraphID = f2.ParagraphID
FOR XML PATH ('')), 1, 1, '') AS FileNameString
FROM [dbo].[CM_Signature] f1
Note the STUFF("...", 1, 1, '') instead of STUFF("...", 1, 2, '').
Because you need to replace 1 char instead of 2 (To remove the first |).
Output:
Daniel|Emma
Also, if you want to have spaces before and after the |, just use this query:
SELECT DISTINCT
ParagraphID
, STUFF((
SELECT N' | ' + CAST([LoginName] AS VARCHAR(255))
FROM [dbo].[CM_Signature] f2
WHERE f1.ParagraphID = f2.ParagraphID
FOR XML PATH ('')), 1, 3, '') AS FileNameString
FROM [dbo].[CM_Signature] f1
Note that this time we removed 3 chars (STUFF("...", 1, 3, '')).
Output:
Daniel | Emma
You were starting your path at position 2 instead of first
SELECT DISTINCT
ParagraphID
, STUFF((
SELECT N'|' + CAST([LoginName] AS VARCHAR(255))
FROM [dbo].[CM_Signature] f2
WHERE f1.ParagraphID = f2.ParagraphID
FOR XML PATH ('')), 1, 1, '') AS FileNameString
FROM [dbo].[CM_Signature] f1 SELECT DISTINCT
ParagraphID
, STUFF((
SELECT N'|' + CAST([name] AS VARCHAR(255))
FROM mytable f2
WHERE f1.paragraphid = f2.paragraphid
FOR XML PATH ('')), 1, 1, '') AS FileNameString
FROM mytable f1
Use this Code:
create table #test (paragraghid int,name VARCHAR(10))
insert into #test values(1929,'Daniel')
insert into #test values(1929,'Emma')
insert into #test values(1935,'Daniel')
select distinct paragraghid,STUFF((select ' | ' + name from #test a
Where a.paragraghid=b.paragraghid for XML PATH('') ),1,2,'') as FilenameString
from #test b
You can write a query as:
DECLARE #CM_Signature table
(
RowId int,
ParagraphID int,
LoginName varchar(10))
Insert into #CM_Signature values
(4,1929,' Daniel'),
(5,1929,' Emma '),
(6,1935,'Daniel')
SELECT DISTINCT
ParagraphID
, STUFF((
SELECT N'| ' + CAST(rtrim(ltrim([LoginName])) AS VARCHAR(255))
FROM #CM_Signature f2
WHERE f1.ParagraphID = f2.ParagraphID
FOR XML PATH ('')), 1, 1, '') AS FileNameString
FROM #CM_Signature f1

SQL - Combine Multiple Columns with Multiple Rows into one row

What I'm trying to do:
I have records in a SQL table where there are 5 columns and thousands of rows.
The rows share duplicate data (i.e. account number) but what makes each unique is that data in one of the columns is different.
As an example:
col1|col2|col3|col4|col5
------------------------
123|abc|456|def|789
123|abc|456|def|date
But the columns can have different values, not necessarily always in column 5.
Here's what I started with:
SELECT TOP (15) stuff((
SELECT ', ' + te.[accountid]
,te.[char1]
,te.[date]
,te.[date2]
,te.[char2]
FROM D AS te
INNER JOIN D AS tue ON tue.[accountid] = te.[accountid]
WHERE tue.[accountid] = ue.[accountid]
FOR XML path('')
,type
).value('.', 'varchar(max)'), 1, 2, '') AS ifile
FROM D AS ue
GROUP BY ue.[accountid]
But I get a monster long string that includes the duplicate rows in one column. I'm not sure what else to try so any insight would be appreciated.
If I had to guess, you have an unnecessary self join in the subquery:
SELECT TOP (15) stuff((
SELECT ', ' + te.[accountid], te.[char1], te.[date], te.[date2], te.[char2]
FROM D te
WHERE te.[accountid] = ue.[accountid]
FOR XML path(''), type
).value('.', 'varchar(max)'), 1, 2, '') AS ifile
FROM D ue
GROUP BY ue.[accountid];
You might also want SELECT DISTINCT in the subquery.
Use UNION to get rid of all the duplicate values and use your FOR XML PATH on the output to append it to a single string:
SELECT TOP (15) stuff((
SELECT ', ' + CAST(te.[accountid] AS varchar(255)) FROM D
UNION
SELECT ', ' + CAST(te.[char1] AS varchar(255)) FROM D
UNION
SELECT ', ' + CAST(te.[date] AS varchar(255)) FROM D
UNION
SELECT ', ' + CAST(te.[date2] AS varchar(255)) FROM D
UNION
SELECT ', ' + CAST(te.[char2] AS varchar(255)) FROM D
FOR XML path('')
,type
).value('.', 'varchar(max)'), 1, 2, '') AS ifile
Untested, treat as pseudo-code to give the general idea.