将函数应用于动态列名

时间:2019-06-14 06:42:59

标签: sql sql-server

我想处理动态数据透视的结果,该结果导致数量可变的不同名称的数据列。但是它们确实包含彼此相关的数据,并且具有相同的数据类型。对于每个结果列,我想应用相同的ISNULL函数。但是由于我不知道各列的名称,因此无法逐列写出操作。

这里是SQL Fiddle。还有一个示例表:

CREATE TABLE T (ID INT UNIQUE NOT NULL, C1 INT NULL, C2 INT NULL, C3 INT NULL);
INSERT INTO T VALUES
    (0, NULL, NULL, NULL),
    (1, 9, NULL, NULL),
    (2, NULL, 8, NULL),
    (3, NULL, NULL, 10),
    (4, 12, 61, NULL),
    (5, 36, NULL, 86),
    (6, NULL, 77, 42),
    (7, 11, 22, 33);

SELECT * FROM T;

 ID |  C1  |  C2  |  C3
----+------+------+-----
 0  | NULL | NULL | NULL
 1  |    9 | NULL | NULL
 2  | NULL |    8 | NULL
 3  | NULL | NULL |   10
 4  |   12 |   61 | NULL
 5  |   36 | NULL |   86
 6  | NULL |   77 |   42
 7  |   11 |   22 |   33

然后将ISNULL(CN, 0)应用于这些列中的每一列。如何实现?如果有任何不同,则由于枢纽查询是动态的,因此此处理将在EXEC sp_executesql内部执行。

那么预期的输出将是:

 ID |  C1  |  C2  |  C3
----+------+------+-----
 0  |    0 |    0 |    0
 1  |    9 |    0 |    0
 2  |    0 |    8 |    0
 3  |    0 |    0 |   10
 4  |   12 |   61 |    0
 5  |   36 |    0 |   86
 6  |    0 |   77 |   42
 7  |   11 |   22 |   33

3 个答案:

答案 0 :(得分:1)

您可以在INFORMATION_SCHEMASTUFFDynamic SQL的帮助下完成此操作:

-- Get the all columns names from the underlying table
SELECT COLUMN_NAME
INTO #TEMP
FROM [Database_Name].INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'T' AND COLUMN_NAME != 'ID'

DECLARE @COLUMNS  NVARCHAR(MAX)
DECLARE @sql NVARCHAR(MAX)

-- Construct a string with ISNULL
SELECT @COLUMNS =  STUFF((SELECT DISTINCT ',ISNULL(' + QUOTENAME(COLUMN_NAME) + ',0) ' + QUOTENAME(COLUMN_NAME) 
FROM #TEMP 
ORDER BY 1 
FOR XML PATH('')), 1, 1, '')

-- and use Dynamic SQL
SELECT @sql = 'SELECT ID,'+ @COLUMNS +' FROM T'

EXEC sp_executesql @sql

答案 1 :(得分:0)

希望这会满足您的要求

CREATE TABLE #T (ID INT UNIQUE NOT NULL, C1 INT NULL, C2 INT NULL, C3 INT NULL);
INSERT INTO #T VALUES
    (0, NULL, NULL, NULL),
    (1, 9, NULL, NULL),
    (2, NULL, 8, NULL),
    (3, NULL, NULL, 10),
    (4, 12, 61, NULL),
    (5, 36, NULL, 86),
    (6, NULL, 77, 42),
    (7, 11, 22, 33);

--SELECT * FROM #T;


  Declare  @Main varchar(max)=''
--use INFORMATION_SCHEMA.COLUMNS for physical table 
        select  @Main += ',isnull('+name+',0) as '+name
         from (select name from tempdb.sys.columns where object_id =object_id('tempdb..#T')) as spt

        set @Main= 'select '+stuff(@Main ,1,1,'') + ' from #T'
        Exec(@Main)

答案 2 :(得分:0)

我不太喜欢STUFF解决方案。并且由于数据透视查询已经是动态的,因此在Raka和该主题的answer的帮助下,我动态生成了列列表。我觉得这段代码更容易理解。

假设PIVOT生成的列在@Columns TABLE (Column VARCHAR)中或类似的位置:

DECLARE @Isnull NVARCHAR(MAX);

SELECT @Isnull = ISNULL(@Isnull + ', ', '') + 'ISNULL(' + QUOTENAME([Column]) + ', 0)'
FROM Columns

EXEC sp_executesql N'SELECT ' + @Isnull + 'FROM whatever PIVOT things'