Concat column values with comma as the separator - sql

I am trying to figure out the result of the below query on how to concat all the columns into a single string with comma separated values. The number of values can be dynamic.
SELECT 'Sc4','Sc5','Sc8','Sc7','Sc2'
I want the result to be as below:
Sc4,Sc5,Sc8,Sc7,Sc2
I have tried using stuff but did manage to concat the string but unable to insert comma in between.
Below is what i have tried
SELECT Stuff((SELECT 'Sc4','Sc5','Sc8','Sc7','Sc2' FOR XML PATH('')), 2, 0, '');
UPDATE
I would like to rephrase my question, is there any way the out shown below can be converted to csv

i assume Sc4, Sc5 etc are your column name and not string constant ?
SELECT Stuff(
(
SELECT ',' + Sc4 + ',' + Sc5 + ',' + Sc8 + ',' + Sc7
+ ',' + Sc2
FROM yourtable
FOR XML PATH('')
), 1, 1, '');

Try concatenation like
SELECT 'Sc4' + ',' + 'Sc5' + ',' + 'Sc8' + ',' + 'Sc7' + ',' + 'Sc2'

Related

Remove all instances of specific value from comma separated string

I want to remove a given value (e.g. 1) from the following string without splitting or using XML functionality.
/* input: */ #ObjectValue = '1,121,4,5,1,111,131,1'
/* output: */ '121,4,5,111,131'
I think the simplest method is:
SELECT TRIM(',' from REPLACE(',' + #ObjectValue + ',', ',1,', ','))
TRIM() is not available in older versions of SQL Server. One method is to replace the commas with spaces and using the available trim functions:
SELECT REPLACE(LTRIM(RTRIM(REPLACE(REPLACE(',' + #ObjectValue + ',', ',1,', ','), ',', ' '))), ' ', ','),
You need to double the delimiters in the list so that 1,1,1 becomes ,1,,1,,1,. Then replace all ,1, and cleanup afterwards:
SELECT ObjectValue, REPLACE(
LTRIM(RTRIM(
REPLACE(' ' + REPLACE(ObjectValue, ',', ' ') + ' ', ' 1 ', '')
)), ' ', ','
)
FROM (VALUES
('1'),
('1,1'),
('1,1,1'),
('0,1,0'),
('0,1,1,0'),
('0,1,1,1,0'),
('0,1,0,1,0'),
('1,0,0,1,0,0,1,1,0,1,0,1,1,1,1,1,0,1,0,0,1,1,0,1,0,1,0,1,0,1')
) AS v(ObjectValue)
-- SSMS 2017
DECLARE #ObjectValue VARCHAR(100) = '1,121,4,5,1,111,131,1'
SELECT TRIM(',' FROM REPLACE(REPLACE(',' + #ObjectValue + ',', ',1,', ','),',1,', ','))
-- SSMS 2016 or earlier
DECLARE #Replacetxt VARCHAR(MAX)
SET #ObjectValue=REPLACE(REPLACE(','+#ObjectValue+',', ',1,', ','), ',1,', ',') --Replace ',1,' with ','
SET #Replacetxt=REVERSE(SUBSTRING(#ObjectValue, PATINDEX('%[^,]%', #ObjectValue), LEN(#ObjectValue))) -- Remove comma from starting and reverse string
SELECT REVERSE(SUBSTRING(#Replacetxt, PATINDEX('%[^,]%', #Replacetxt), LEN(#ObjectValue))) -- Remove comma from ending and reverse string

comma separated column values

I need to take the values from 3 columns and group them into 1 column as comma separated:
2014-01-01,2014-01-29
The problem is that one or more columns can be NULL and therefore it messes up the commas as such:
2014-01-01,,2014-01-29
This is how I have it coded (the case statement basically just strips out a comma if it's the last character in the string.
I need to add some logic so that it takes into account NULLs but I'm having a hard time coming up with it.
CASE WHEN RIGHT(ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate, 1) = ','
THEN LEFT(ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate, LEN(ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate) - 1)
ELSE ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate
END AS AlLGapDatesFormatted
EDIT -
I need to group the highlighted (notice that PayrollGapDate is ''):
And this is what I'm getting:
And this is the code I implemented:
try using this technique:
SET CONCAT_NULL_YIELDS_NULL ON --<<<make sure concatenations with NULL result in NULL
DECLARE #C1 varchar(10)='AAA'
,#C2 varchar(10)='BBB'
,#C3 varchar(10)=null
,#C4 varchar(10)='DDD'
SELECT STUFF( ISNULL(', '+#C1,'')
+ISNULL(', '+#C2,'')
+ISNULL(', '+#C3,'')
+ISNULL(', '+#C4,'')
,1,2,''
)
output:
-----------------------------------------------
AAA, BBB, DDD
(1 row(s) affected)
You let the ', '+#C3 result in NULL, which the ISNULL(***,'') converts to empty string. The STUFF(***,1,2,'') removes the leading comma and space.
try:
SELECT STUFF( ISNULL(', '+d.FirstGapDate,'')
+ISNULL(', '+d.PayrollGapDate,'')
+ISNULL(', '+d.LastGapDate,'')
,1,2,''
)
FROM ...
WHERE...
You can apply something like this above your expression to replace many commas with one comma:
declare #s varchar(100) = 'ABC,,,,DEF'
select replace(replace(replace(#s, ',', '[]'), '][', ''), '[]', ',')

Add selected values from multi column into one column separated by ','

I want to select values from multiple columns into one column. I have 2 separate columns from which i want to get name,address,state,zip in following format in SQL Server 2008
Name (new line)
address,state,zip
Name (new line)
address,state,zip
Query:
select
name + char(13) + concat(address,',', state,',', zip)
from
tbl1
join
tbl2 on....
I am not able to get the desired output. I get concat is not a recognized built in function name.
You could use + operator and cast the zip field as varchar directly like this:
For example:
select 'Dara Singh' + char(13) + '1234 Main Street' + ',' + 'NY' + ','
+ cast(95825 as varchar(10))
This is how your query would look:
select name + char(13) + [address] + ',' + [state] + ',' + cast([zip] as varchar(10))
from tbl1 join tbl2 on....

Concatenation of strings by for xml path

Hi!
Today I learned for xml path technique to concatenate strings in mssql. Since I've never worked with xml in mssql and google hasn't helped, I need to ask you.
Let's imagine the default case. We need to concatenate some strings from a table:
declare #xmlRepNames xml = (
select
', [' + report_name + ']'
from (
select distinct
report_order,
report_name
from #report
) x
order by
report_order
for xml path(''), type)
select
stuff((select #xmlRepNames.value('.', 'nvarchar(max)')), 1, 1, '')
So I get smth like this:
[str1], [str2], [strn]
Ok. It works fine. But I have two very similar concatenate blocks. The difference is just in the way the result string looks like:
[str1], [str2], [strn]
and
isnull([str1], 0) as [str1], isnull([str2], 0) as [str2], isnull([strn], 0) as [strn]
So I can write 2 very similar code blocks (already done, btw) with different string constructors or to try extend previous code to has xml variable containing 2 kind of constructors and then concatenate by xml node type. Doing 2nd way I met some problems - I wrote this:
declare #xmlRepNames xml = (
select
', [' + report_name + ']' as name,
', isnull([' + report_name + '], 0) as [' + report_name + ']' as res
from (
select distinct
report_order,
report_name
from #report
) x
order by
report_order
for xml path(''), type)
select
stuff((select #xmlRepNames.value('/name', 'nvarchar(max)')), 1, 1, ''),
stuff((select #xmlRepNames.value('/res', 'nvarchar(max)')), 1, 1, '')
but it raise error "XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'".
To replace, e.g., '/name' to '/name[1]' or any other '/name[x]', will return just x-th 'name' record but not all 'name' records concatenated.
[question]: is it possible to solve problem 2nd way like I want and if it's possible then how?
[disclaimer]: the problem isn't really serious for me now (1st way just a little bit uglier but also fine), but it seems very interesting how to come over :)
Thanks!
Your subquery cannot return two values. If you just want to concatenate strings, you do not need the xml data type at all. You can do the stuff() and subquery in a single statement:
declare #Rep1Names nvarchar(max) = (
stuff((select ', [' + report_name + ']' as name
from (select distinct report_order, report_name
from #report
) x
order by report_order
for xml path('')
)
), 1, 1, '');
declare #Rep2Names nvarchar(max) = (
stuff(select ', isnull([' + report_name + '], 0) as [' + report_name + ']' as res
from (select distinct report_order, report_name
from #report
) x
order by report_order
for xml path('')
)
), 1, 1, '');
Ok, so I haven't been completely satisfied the way Gordon Linoff suggested and since I've found this kind of problem actual for me I'm adding here another solution without using for xml path:
declare
#pivot_sequence nvarchar(max),
#columns_sequence nvarchar(max)
select
#pivot_sequence = coalesce(#pivot_sequence + ', [', '[')
+ col_name + ']',
#columns_sequence = coalesce(#columns_sequence + ', ', '')
+ 'isnull([' + col_name + '], 0) as [' + col_name + ']'
from some_table
order by
/* some_columns if needed to order concatenation */
Obviously, it'll work much slower but in cases when you haven't many rows it won't drastically affect on performance. In my case I have dynamic pivot query and these strings are built for it - I won't have many columns in pivot so it's fine for me.

How can I combine multiple rows into a comma-delimited list in SQL Server 2005?

Right now, I have a SQL Query like this one:
SELECT X, Y FROM POINTS
It returns results like so:
X Y
----------
12 3
15 2
18 12
20 29
I'd like to return results all in one row, like this (suitable for using in an HTML <AREA> tag):
XYLIST
----------
12,3,15,2,18,12,20,29
Is there a way to do this using just SQL?
Thanks for the quick and helpful answers guys!
I just found another fast way to do this too:
SELECT STUFF(( SELECT ',' + X + ',' + Y
FROM Points
FOR
XML PATH('')
), 1, 1, '') AS XYList
Credit goes to this guy:
Link
DECLARE #XYList varchar(MAX)
SET #XYList = ''
SELECT #XYList = #XYList + CONVERT(varchar, X) + ',' + CONVERT(varchar, Y) + ','
FROM POINTS
-- Remove last comma
SELECT LEFT(#XYList, LEN(#XYList) - 1)
Using the COALESCE trick, you don't have to worry about the trailing comma:
DECLARE #XYList AS varchar(MAX) -- Leave as NULL
SELECT #XYList = COALESCE(#XYList + ',', '') + CONVERT(varchar, X) + ',' + CONVERT(varchar, Y)
FROM POINTS
Starting in SQL 2017, you can use STRING_AGG
SELECT STRING_AGG (X + ',' + Y, ',') AS XYLIST
FROM POINTS
https://learn.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-2017
DECLARE #s VarChar(8000)
SET #s = ''
SELECT #s = #s + ',' + CAST(X AS VarChar) + ',' + CAST(Y AS VarChar)
FROM POINTS
SELECT #s
Just get rid of the leading comma