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
Related
I am still getting separated rows even though there are many instances where the branches should be grouped with a single string output containing the branch list of emails.
SELECT
upv1.PropertyVal AS [Branch],
STUFF((SELECT '; ' + CAST(upv2.propertyval AS VARCHAR(36))
FROM upa.UserProfileValue upv2
WHERE upv1.RecordID = upv2.RecordID
AND upv2.PropertyID = 9
FOR XML PATH('')), 1, 2, '') [Emails]
FROM
upa.UserProfileValue upv1
WHERE
upv1.PropertyID = 11
AND upv1.PropertyVal <> 'Missing Branch'
GROUP BY
upv1.PropertyVal, upv1.RecordID
ORDER BY
upv1.PropertyVal
remove upv1.RecordID from group by clause
SELECT
upv1.PropertyVal as [Branch],
STUFF((select '; ' + cast(upv2.propertyval as varchar(36))
from upa.UserProfileValue upv2
where upv1.RecordID = upv2.RecordID
and upv2.PropertyID = 9
FOR XML PATH('')), 1, 2, '') [Emails]
FROM upa.UserProfileValue upv1
where upv1.PropertyID = 11
and upv1.PropertyVal <> 'Missing Branch'
group by upv1.PropertyVal
order by upv1.PropertyVal
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
TitemName and TshotName is the problem here
SELECT DISTINCT
tJobs.* ,
tCustomer.Name AS Customer_name ,
(SELECT tEmployee.First + ' ' + tEmployee.Last
FROM tEmployee
WHERE tEmployee.EmployeeID = tJobs.AccountExecutiveID) AS AccountExecutive,
(SELECT tEmployee.First + ' ' + tEmployee.Last
FROM tEmployee
WHERE tEmployee.EmployeeID = tJobs.AccountManagerID) AS AccountManager,
dbo.RetrunUserFavourite(tJobs.JobNumber, 33369, 'Employee') AS Favorites,
(SELECT COUNT(*)
FROM tShots
WHERE tShots.JobNumber = tJobs.JobNumber) AS shotcount,
SUBSTRING((SELECT ', ' + SKU + ', ' + Source + ', ' + ModelNumber
+ ', ' + Description
FROM tItems
WHERE tItems.CustomerID = tCustomer.CustomerID
FOR XML PATH('')), 3, 200000) titemName,
SUBSTRING((SELECT ', ' + ArtDirection + ', '
+ REPLACE(CONVERT(VARCHAR(5), AdDate, 110), '-',
'/')
FROM tShots
WHERE tShots.JobNumber = tJobs.JobNumber
FOR XML PATH('')), 3, 200000) TshotName
FROM
tJobs
INNER JOIN
tCustomer ON tCustomer.CustomerID = tJobs.CustomerID
WHERE
tCustomer.CustomerID = 68666
I strongly agree with M Ali's comments. Two points I would make. The first is not with regard to performance. But, instead of substring() use:
STUFF((SELECT ', ' + SKU + ', ' + Source + ', ' + ModelNumber+ ', ' + Description
FROM tItems
WHERE tItems.CustomerID = tCustomer.CustomerID
FOR XML PATH('')
), 1, 1, '') as titemName
That way, you don't need strange, meaningless numbers floating around the code.
Second, you may need indexes. Based on the highlighted performance problems, I would suggest:
tItems(CustomerID)
and:
tshots(JobNumber, ArtDirection, AdDate)
You have awful lot of string manipulation going on is your query, anyway a slightly improved version of your query would look something like...
Select DISTINCT
tJobs.*
, tCustomer.Name AS Customer_name
, AE.First + ' ' + AE.Last AS AccountExecutive
, AM.First + ' ' + AM.Last AS AccountManager
, dbo.RetrunUserFavourite(tJobs.JobNumber,33369,'Employee')AS Favorites
, TS.shotcount
, SUBSTRING(( SELECT ', ' + SKU + ', ' + Source + ', ' + ModelNumber+ ', ' + Description
FROM tItems
where tItems.CustomerID=tCustomer.CustomerID
FOR XML PATH('')), 3, 200000)titemName
, SUBSTRING(( SELECT ', ' + ArtDirection +', '+REPLACE(CONVERT(VARCHAR(5),AdDate,110), '-','/')
FROM tShots
where tShots.JobNumber=tJobs.JobNumber
FOR XML PATH('')), 3, 200000)TshotName
From tJobs
inner join tCustomer on tCustomer.CustomerID = tJobs.CustomerID
Left join tEmployee AE ON AE.EmployeeID = tJobs.AccountExecutiveID
Left join tEmployee AM ON AM.EmployeeID = tJobs.AccountManagerID
Left join (
SELECT JobNumber , Count(*) shotcount
FROM tShots
GROUP BY JobNumber
) TS ON TS.JobNumber = tJobs.JobNumber
WHERE tCustomer.CustomerID = 68666
A Couple of Pointers:
Having sub-queries in your select statement makes it very inefficient, because the sub-query is executed for each row returned by the outer query, a more sensible way of doing it would be to use joins.
You Also have a call to a User-Defined Scalar function dbo.RetrunUserFavourite() in your select , these scalar UDFs are also performance killers, again the same execution logic is applied here, they are also executed for each row returned by the outer query, a more sensible way would be to put the function logic/code inside a CTE and join your query to that CTE.
These comma delimited lists that you are creating on the fly for last two columns will be slow, maybe an Inline-Table-Valued function can give better performance here.
How can I join these 2 SQL statements? I want the columns of the first and the columns of the second to appear together as one SQL query.
SELECT
E.tbl1_ORG AS Organización, E.tbl1_CODE AS [Orden de Trabajo],
E.tbl1_OBJECT AS Equipo, O.tbl3_POSITION AS Posicion,
E.tbl1_JOBTYPE AS [Tipo de Trabajo],
E.tbl1_DESC AS [Descripcion OT], E.tbl1_WORKADDRESS AS Comentarios,
E.tbl1_REQM AS Error, B.tbl2_PERSON AS Trabajador,
B.tbl2_ENTERED AS Fecha, B.tbl2_HOURS AS Horas
FROM
dbo.table1 AS E
INNER JOIN
dbo.table2 AS B ON E.tbl1_CODE = B.tbl2_EVENT
INNER JOIN
dbo.table3 AS O ON O.tbl3_CODE = E.tbl1_OBJECT
WHERE
E.tbl1_JOBTYPE IN ('PM', 'CM', 'PMM') and
E.tbl1_ORG = #PROMPT('Organización')# and
B.tbl2_ENTERED between #PROMPT('Fecha_Inicio')# and #PROMPT('Fecha_Final')# and
(E.tbl1_REQM = #PROMPT('Error')# OR #PROMPT('Error')# = '%') and
(E.tbl1_OBJECT = #PROMPT('Equipo')# OR #PROMPT('Equipo')# = '%') and
(O.tbl3_POSITION = #PROMPT('Posicion')# OR #PROMPT('Posicion')# = '%')
And:
SELECT
tbl2_event 'Orden de Trabajo',
STUFF((SELECT ', ' + CAST(tbl2_person AS VARCHAR(100)) [text()]
FROM table2
WHERE tbl2_event = t.tbl2_event
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,1,' ') Empleados,
STUFF((SELECT ', ' + CAST(tbl2_hours AS VARCHAR(100)) [text()]
FROM table2
WHERE tbl2_event = t.tbl2_event
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'), 1, 1, ' ') Horas
FROM table2 t
GROUP BY tbl2_event
Both work perfectly on their own, but I don't know how to merge them.
Add ROW_NUMBER to each query and then FULL JOIN them together. You'll need to decide on the ordering of rows in each query.
WITH
CTE1
AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY ...) AS rn,
E.tbl1_ORG AS Organización, E.tbl1_CODE AS [Orden de Trabajo],
E.tbl1_OBJECT AS Equipo, O.tbl3_POSITION AS Posicion,
E.tbl1_JOBTYPE AS [Tipo de Trabajo],
E.tbl1_DESC AS [Descripcion OT], E.tbl1_WORKADDRESS AS Comentarios,
E.tbl1_REQM AS Error, B.tbl2_PERSON AS Trabajador,
B.tbl2_ENTERED AS Fecha, B.tbl2_HOURS AS Horas
FROM
dbo.table1 AS E
INNER JOIN
dbo.table2 AS B ON E.tbl1_CODE = B.tbl2_EVENT
INNER JOIN
dbo.table3 AS O ON O.tbl3_CODE = E.tbl1_OBJECT
WHERE
E.tbl1_JOBTYPE IN ('PM', 'CM', 'PMM') and
E.tbl1_ORG = #PROMPT('Organización')# and
B.tbl2_ENTERED between #PROMPT('Fecha_Inicio')# and #PROMPT('Fecha_Final')# and
(E.tbl1_REQM = #PROMPT('Error')# OR #PROMPT('Error')# = '%') and
(E.tbl1_OBJECT = #PROMPT('Equipo')# OR #PROMPT('Equipo')# = '%') and
(O.tbl3_POSITION = #PROMPT('Posicion')# OR #PROMPT('Posicion')# = '%')
)
,CTE2
AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY ...) AS rn,
tbl2_event 'Orden de Trabajo',
STUFF((SELECT ', ' + CAST(tbl2_person AS VARCHAR(100)) [text()]
FROM table2
WHERE tbl2_event = t.tbl2_event
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,1,' ') Empleados,
STUFF((SELECT ', ' + CAST(tbl2_hours AS VARCHAR(100)) [text()]
FROM table2
WHERE tbl2_event = t.tbl2_event
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'), 1, 1, ' ') Horas
FROM table2 t
GROUP BY tbl2_event
)
SELECT ...
FROM
CTE1 FULL JOIN CTE2 ON CTE1.rn = CTE2.rn
ORDER BY ...
;
If you have more than 2-3 tables to join like this FULL JOIN would quickly become ugly and slow. Have a look at my answer for a similar question for alternative solution: best way to "glue" columns together
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'