选择非空列作为动态sql

时间:2019-04-05 09:15:52

标签: sql sql-server tsql sql-server-2016 dynamic-sql

我正在尽力避免使用游标。 nvarchar变量中有一个用逗号分隔的列列表,如下所示:

@columnList = 'col1,col2,col5'

有一个包含很多varchar列的表:

myTable: [col1],[col2],[col3],[col4],[col5],[col6],[col7]

这是我使用动态sql选择数据的方式:

exec ('select ' + @columnList + ' from myTable')

此查询返回以下结果:

[col1], [col2] , [col5]
 null , "txt1" ,  null
"txt2",  null  ,  null
 null , "txt3" , "txt4"

这就是我需要得到的:

@resultList = "txt1,txt2,txt3,txt4"

如何选择仅包含非空值的逗号分隔字符串?我知道如何将表转换为逗号分隔的字符串,因此得到如下信息:

 [column]
  "txt1"
  "txt2"
  "txt3"
  "txt4"

也可以。有什么建议么?随意提出一种基本方法,我不希望您为我编写实际的代码。

3 个答案:

答案 0 :(得分:2)

您可以使用以下解决方案,仅使用REPLACE来创建SQL查询:

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');

您还可以通过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

答案 1 :(得分:0)

由于您提到了您已经知道如何聚合成逗号分隔的内容,因此以下是使用交叉应用取消透视表的方法:

select unpivoted.*
from myTable
cross apply
( values
     ('col1',col2)
    ,('col2',col2)
    ,('col3',col3) -- etc
)unpivoted(colname,colval)

答案 2 :(得分:0)

这适用于SQL Server 2017,在早期版本STRING_AGG上的用法应替换为XML-based solution

您可以先将结果串联成一行,然后使用STRING_AGG将结果汇总成一个字符串:

;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仅用于展示,您可以在动态查询中简单地做到这一点:

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