Use STUFF function to insert at multiple points in a string?
-
10-10-2020 - |
Question
Is there a way that I can replace a substring in SQL server while remaining 'aware' of what I'm replacing so that I can then re-insert that content?
I am building a string of column names to pivot on, and these column names need to be aggregated on in the query.
For example, I have this list of columns as an nvarchar(max) string:
[A], [B], [C]
And I would like to transform this string to look like this:
sum([A]) [A], sum([B]) [B], sum([C]) [C],
I have just found the stuff
function but I don't know how to achieve what I want yet.
But I get the feeling that I can use it to insert substrings instead of using replacing substrings.
Looking at the stuff function:
STUFF( source_string, start, length, add_string )
How do you insert into multiple locations at once?
My current solution is this:
declare @cols nvarchar(max);
declare @colsAggregate nvarchar(max);
declare @sql nvarchar(max);
select @cols = stuff((
select distinct ',' + quotename(sCode)
from EntityList EL
where EL.bActive = 1 for xml path(''), type).value('.', 'nvarchar(max)'),
1, 1, '');
select @colsAggregate = stuff((
select distinct ', max(' + quotename(sCode) + ') ' + quotename(sCode)
from EntityList EL
where EL.bActive = 1 for xml path(''), type).value('.', 'nvarchar(max)'),
1, 1, '');
Solution
You need to get it as rows before you can use STUFF.
DECLARE @rows nvarchar(max) = '[A],[B],[C]'; DECLARE @cols nvarchar(max); SELECT LTRIM(RTRIM(j.value)) FROM STRING_SPLIT(@rows, ',') j SET @cols = STUFF((SELECT ', ' + (col) FROM (SELECT LTRIM(RTRIM(j.value)) col FROM STRING_SPLIT(@rows, ',') j) Foo FOR XML PATH(''), TYPE ).value('.', 'nvarchar(MAX)') ,1,2,''); SELECT @cols; SET @cols = STUFF((SELECT ', ' + ('SUM(' + col + ')') FROM (SELECT LTRIM(RTRIM(j.value)) col FROM STRING_SPLIT(@rows, ',') j) Foo FOR XML PATH(''), TYPE ).value('.', 'nvarchar(MAX)') ,1,2,''); SELECT @cols; SET @cols = STUFF((SELECT ', ' + ('SUM(' + col + ') ' + col) FROM (SELECT LTRIM(RTRIM(j.value)) col FROM STRING_SPLIT(@rows, ',') j) Foo FOR XML PATH(''), TYPE ).value('.', 'nvarchar(MAX)') ,1,2,''); SELECT @cols; GO
| (No column name) | | :--------------- | | [A] | | [B] | | [C] | | (No column name) | | :--------------- | | [A], [B], [C] | | (No column name) | | :--------------------------- | | SUM([A]), SUM([B]), SUM([C]) | | (No column name) | | :--------------------------------------- | | SUM([A]) [A], SUM([B]) [B], SUM([C]) [C] |
dbfiddle here