简体   繁体   中英

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM