Hi,
When you ask a question and present some info then please focus on the issue. It seems like in your case you want to use STRING_AGG
function instead of using using FOR AML
(by the way, stuff
is not what aggregate the data but the FOR XML part). The idea is to simplifies the scenario and present a full demo which focus on the issue.
In your query you are using dynamic query. How this is relevant to the issue?!?
(1) PRINT the query instead of Execute it in order to get the query which you ask about
(2) Once I print the query I see that you have INSERT... SELECT, but only the SELECT part is relevant to the question, so why do you need to present us complex query instead focus on the SELECT?
(3) In the SELECT query you have multiple columns which are not related to the question. For example, the SELECT of this part PartID,Code,Co.CodeTypeID,Co.RevisionID,Co.ZPLID,Count(1) as ConCount,
is not relevant to question since you only want to understand how to change the last two columns which uses FOR XML
to use STRING_AGG
, so we can simplifies the query for the sake of the question to select only the last two relevant columns.
In fact, lets focus on one column first, since the solution is the same.
Can you understand that we could focus on the following query for the sake of the discussion? Will a solution for the following query solve your needs?
SELECT stuff(
( SELECT '$' + CAST( CP.ColumnName AS VARCHAR(500)) AS [text()]
FROM (
SELECT distinct d.ColumnName,C.codeTypeId,C.Code,C.ZfeatureKey
from ExtractReports.dbo.TCondition C with(nolock)
inner join core_datadefinitiondetails d with(nolock)
on C.ZfeatureKey=d.columnnumber
INNER JOIN ExtractReports.dbo.TPartAttributes P with(nolock)
on P.partid=PM.partid
)CP
where CP.codeTypeId=Co.codeTypeId and CP.Code=Co.Code
ORDER BY CP.ZfeatureKey
FOR XML PATH('')
)
, 1, 1, ''
) as FeatureName
(4) In the above query, the sub-query inside the FROM is a simple SELECT query. It can be replaced with any other query. This is not relevant to your question. right?
Therefore, for the sake of the discussion regarding your question you could presented us a simpler query like:
SELECT stuff(
( SELECT '$' + CAST( CP.ColumnName AS VARCHAR(500)) AS [text()]
FROM CP
where CP.codeTypeId=Co.codeTypeId and CP.Code=Co.Code
ORDER BY CP.ZfeatureKey
FOR XML PATH('')
)
, 1, 1, ''
) as FeatureName
The original query uses two tables: ExtractReports.dbo.TPartAttributes
with the alias PM and ExtractReports.dbo.TCondition
with the alias Co
The use of Co
is only in the WHERE
part, and the this part is not relevant to the question, so let's remove it to focus on simpler query which uses one simple table.
In your case, after I clean the not-relevant information, then basically you have two queries which looks like this:
SELECT stuff(
(SELECT '$' + CP.ColumnName
FROM CP
ORDER BY CP.ZfeatureKey
FOR XML PATH('')
)
, 1, 1, ''
) as FeatureName
GO
You should ALWAYS provide relevant table(s) with some data for the sake of the discussion.
For such question using the above simplified query we need a table CP (no need for all the real original table which sued for JOIN query but just simplified it to simple table) with the columns ColumnName, ZfeatureKey
So this is the simple DDL+DML (queries to create the table and insert sample data) which we can present the question and discuss the answer on
DROP TABLE IF EXISTS CP;
GO
CREATE TABLE CP(ColumnName NVARCHAR(100), ZfeatureKey int)
GO
INSERT CP(ColumnName, ZfeatureKey) VALUES ('a',1),('b',3),('c',2),('d',6),('e',4)
GO
And now we can present the solution for this simple case:
-- Using FOR XML
SELECT stuff(
(SELECT '$' + CP.ColumnName
FROM CP
ORDER BY CP.ZfeatureKey
FOR XML PATH('')
)
, 1, 1, ''
) as FeatureName
GO
-- Using STRING_AGG
SELECT STRING_AGG(ColumnName,'$') WITHIN GROUP (ORDER BY ZfeatureKey)
FROM CP
GO
Try to implement this simple case in your real case
Basically you have two places where you use FOR XML
which you can now replace with using STRING_AGG
function.