Comma separated column value from Temporary Table - sql

I am inserting select statement result to Temporary table. I want its one column value comma separated, so I tried following but it is not working.
SELECT #IdList = COALESCE(#IdList+',' ,'') + s.Id
FROM (SELECT Id FROM #_TempStudentTable) as s
I have checked data in #_TempStudentTable, it is having data. But when i try to display IdList, it returns NULL.
Help me. I don't know what's the problem.

Try this :
DECLARE #IdList VARCHAR(MAX)
SELECT #IdList = COALESCE(#IdList + ',','') + CAST(Id AS VARCHAR(100))
FROM #_TempStudentTable
SELECT #IdList
You can get it without variable also using XML like below
SELECT STUFF(( SELECT ',' + CAST(Id AS VARCHAR(10))
FROM #_TempStudentTable
FOR XML PATH (''))
, 1, 1, '')

In SQL Server, you may use the below query to get a list of comma separated column names/headers:
SELECT STUFF((
SELECT ',' + CAST(name AS VARCHAR(50))
FROM (
SELECT name
FROM tempdb.sys.columns
WHERE [object_id] = OBJECT_ID(N'tempdb..#temptablename')
) k
FOR XML PATH('')
), 1, 1, '')

Related

Select not null columns as a comma separated string from dynamic sql

I am trying to do my best to avoid using cursors. There is a comma separated list of columns in nvarchar variable that looks like this:
#columnList = 'col1,col2,col5'
There is a table with lots of varchar columns:
myTable: [col1],[col2],[col3],[col4],[col5],[col6],[col7]
This is how I select data using a dynamic sql:
exec ('select ' + #columnList + ' from myTable')
This query returns the following results:
[col1], [col2] , [col5]
null , "txt1" , null
"txt2", null , null
null , "txt3" , "txt4"
This is what I need to get:
#resultList = "txt1,txt2,txt3,txt4"
How do I select a comma separated string containing not-null values only? I know how to convert a table to comma separated string, so getting something like:
[column]
"txt1"
"txt2"
"txt3"
"txt4"
Is also fine. Any suggestions? Feel free to suggest a basic approach, I don't expect you to write the actual code for me.
You can use a solution like the following, using just a REPLACE to create the SQL query:
DECLARE #columnList VARCHAR(100)
SET #columnList = 'col1,col2,col5'
SET #columnList = REPLACE(#columnList, ',', ' AS colName FROM myTable UNION ALL SELECT ');
EXEC('SELECT * FROM (SELECT ' + #columnList + ' AS colName FROM myTable)t WHERE NOT t.colName IS NULL');
You can also use a solution using UNPIVOT:
DECLARE #columnList VARCHAR(100);
SET #columnList = 'col1,col2,col5';
EXEC('SELECT colName FROM (SELECT ' + #columnList + ' FROM myTable) t1 UNPIVOT (colName FOR columnNames IN (' + #columnList + ')) AS t2');
demo on dbfiddle.uk
Since you mention you already know how to aggregate into comma-seperated, here's how to unpivot your table with cross apply:
select unpivoted.*
from myTable
cross apply
( values
('col1',col2)
,('col2',col2)
,('col3',col3) -- etc
)unpivoted(colname,colval)
This would work for SQL Server 2017, on earlier version STRING_AGG usage should be replaced with XML-based solution.
You could first concatenate your results into a single line and then use STRING_AGG to aggregate them into a single string:
;with t as
(
SELECT * FROM (VALUES
(null , 'txt1' , null),
('txt2', null , null),
(null , 'txt3' , 'txt4')) x(col1, col2, col5)
)
SELECT STRING_AGG(STUFF(CONCAT(',' + col1, ',' + col2, ',' + col5), 1, 1, ''), ',')
FROM t
CTE is just for showcasing, you can simply do it in your dynamic query:
DECLARE #columnList NVARCHAR(MAX) = 'col1,col2,col5'
DECLARE #query NVARCHAR(MAX) = ''
SELECT #query = 'SELECT STRING_AGG(STUFF(CONCAT('','' + ' + REPLACE(#columnList, ',', ', '','' + ') + '), 1, 1, ''''), '','') from mytable'
EXEC sp_executesql #query
Working example on dbfiddle

Return SELECT query result as a CSV string

I have the following Sql Server 2016 SELECT statement that returns only 1 row:
SELECT TOP 1 * FROM tempdb.dbo.IMTD
How can I concatenate the values as a comma delimited string? NOTE: the column names of this temporary table are unknown as they can variate.
Thank you.
Something like this perhaps:
-- Sample data
DECLARE #someTable TABLE (SomeID int identity, SomeTxt varchar(100));
INSERT #someTable VALUES ('row1'),('row2'),('row3');
-- Solution
SELECT ConcatinatedString =
STUFF
((
SELECT ','+SomeTxt
FROM #someTable
FOR XML PATH(''), TYPE
).value('.','varchar(100)'),1,1,'');
You can use Dynamic query as below:
DECLARE #COLS VARCHAR(MAX) = ''
SELECT #COLS = #COLS + ',' + COLUMN_NAME
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE '#table[_]%' -- Dynamic Table (here, Temporary table)
DECLARE #COLNAMES VARCHAR(MAX) = REPLACE(STUFF(#COLS, 1, 1, ''), ',', '+ '','' +')
Declare #cmd varchar(max) = 'Select ' + #COLNAMES + ' as CSVCol from #table'
-- will generate
-- Select Column1+ ',' +Column2+ ',' +Column3 as CSVCol from #table
EXEC (#cmd)
Another solution you can try is this.
SELECT LTRIM(RTRIM(<ColumnName1>)) + ',',
LTRIM(RTRIM(<ColumnName2>)) + ',',
...
LTRIM(RTRIM(<ColumnNamen>)) + ','
FROM tempdb.dbo.IMTD
If you only want one row keep that top 1 In there like
SELECT TOP 1
LTRIM(RTRIM(<ColumnName1>)) + ',',
LTRIM(RTRIM(<ColumnName2>)) + ',',
...
LTRIM(RTRIM(<ColumnNamen>)) + ','
FROM tempdb.dbo.IMTD
The LTRIM and RTRIM will remove any white space and this should allow you to copy and paste the result set anywhere you may need it. You will need to do this for each columnname.
You can use the query below to get the column names from your temp table.
DECLARE #ColumnNames NVARCHAR(MAX)
SELECT
#ColumnNames= COALESCE(#ColumnNames +',','')+COLUMN_NAME
FROM
TempDB.INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = '#TempTableName'

SQL create distinct comma separated lists

I have a stored procedures that accepts a comma separated list, then makes copies of that list with quoted strings and brackets, then uses those in a dynamic sql statement to build a pivot table with flexible number of columns.
My problem is that sometimes my users submit a list with duplicates, and that makes the pivot query fail. So I want to somehow select distinct from my comma separated strings.
Here's how I manipulate the initial string:
Declare #data varchar(max) = '150593, 150593, 150603, 150578, 150604'
Declare #bracketed varchar(max) = ''
Declare #quoted varchar(max) = ''
select #bracketed = #bracketed + quotename(rtrim(ltrim(Value))) + ', ',
#quoted = #quoted + quotename(rtrim(ltrim(Value)), '''') + ', '
from [dbo].[fnSplitStringAsTable](#data, ',')
Select #bracketed = LEFT(#bracketed, len(#bracketed) - 1),
#quoted = LEFT(#quoted, len(#quoted) - 1)
I'm thinking I should be able to add DISTINCT somewhere in this query,
but I can't make it work. How can I select distinct from comma separated lists?
as an alternative solution you can dedupe in xml and convert back to varchar
Declare #data varchar(max) = '150593, 150593, 150603, 150578, 150604'
set #data= (select '''' + cast(cast('<d>'+replace(#data, ', ',',</d><d>')+'</d>' as xml).query('distinct-values(/d)') as varchar) +'''')
select #data
I guess we can add in distinct after you make the table, like this:
select #bracketed = #bracketed + quotename(rtrim(ltrim(Value))) + ', ',
#quoted = #quoted + quotename(rtrim(ltrim(Value)), '''') + ', '
from (
SELECT DISTINCT Value FROM [dbo].[fnSplitStringAsTable](#data, ',')
) T
If this fails try this:
select #bracketed = #bracketed + quotename(Value) + ', ',
#quoted = #quoted + quotename(Value), '''') + ', '
from (
SELECT DISTINCT RTRIM(LTRIM(Value)) AS Value FROM [dbo].[fnSplitStringAsTable](#data, ',')
) T
With a little dynamic sql, you can select distinct values from your string variable into a table variable, and then put those values back into the original variable:
declare #data varchar(max) = '150593, 150593, 150603, 150578, 150604'
declare #table table(data varchar(10))
set #data = 'select distinct value from (values (''' +
replace(#data,', ','''),(''') + ''')) as v(value)'
insert into #table
exec(#data)
set #data = ''
select #data = #data + data +
case row_number() over(order by data desc)
when 1 then ''
else ','
end
from #table
order by data asc
select #data

Return two rows as a single row

Please see the SQL DDL below:
create table dbo.Test(id int, name varchar(30))
INSERT INTO Test values (1, 'Mark')
INSERT INTO Test values (2,'Williams')
I am trying to return: 'Mark Williams' using an SQL SELECT. I have tried using an SQL Pivot, but it has not worked.
Possibly more flexible than COALESCE would be to use the STUFF and FOR XML pattern:
SELECT TOP 1
STUFF((SELECT ' ' + Name AS [text()]
FROM dbo.Test
ORDER BY id
FOR XML PATH('')), 1, 1, '' ) Concatenated
FROM TEST
Try this:
DECLARE #Return VARCHAR(MAX)
SELECT #Return = COALESCE(#Return+' ','') + name
FROM dbo.TEST
SELECT #Return
DECLARE #NameList VARCHAR(8000)
SELECT #NameList = COALESCE(#NameList + ' ', '') + Name
FROM Test
SELECT #NameList
Read more COALESCE

SQL Concatenate ids into a specific order

I have the following query which works great, it puts all my ids in a comma separated list.
DECLARE #tmp nvarchar(max)
SET #tmp = ''
SELECT #tmp = #tmp + cast(id as nvarchar(max)) + ', '
FROM dbo.property
I want to put my ids in alphabetical order but when I add order by p.Name it only gives my the top one result.
How can I adapt my query to accomplish this?
This really doesn't work?
DECLARE #tmp nvarchar(max);
SET #tmp = '';
SELECT #tmp = #tmp + cast(id as nvarchar(max)) + ', '
FROM dbo.property p
order by p.name;
In any case, you can use this method:
select #tmp = stuff((select ', ', cast(id as nvarchar(max))
from db.property p
order by p.name
for xml path ('')
), 1, 2, '');
The solution:
SELECT (cast(ID as nvarchar(max)) + ', ') AS [text()]
FROM dbo.property
ORDER BY ID
FOR XML PATH ('')