SQL Server中有什么方法可以有条件地返回列?

时间:2020-07-27 18:14:58

标签: sql sql-server

我有一个存储过程,它返回一堆带编号的列(我知道这是一个坏主意,但这就是它的作用),例如问题1,答案1,...问题125,答案125。

现在,我的问题是,如果要将此过程的结果导出到Excel,则当多于256列时会出现错误。而且查询中有少数未编号的列,所以我总共有262个-但是其中一些是空白的,因为存储过程不一定需要填充所有125个问题和答案。

有什么方法可以编写一个SQL查询,该查询将根据参数有条件地返回许多列?我知道我可以在参数上写一个if语句来返回X的列数或Y,具体取决于是否设置了该参数,但是我想对其进行更细粒度的控制...因此,如果我要处理的数据例如,只有50个问题,那么它将达到Question50 / Answer50。

1 个答案:

答案 0 :(得分:0)

您可以使用SQL Server的FOR XML忽略NULL值并建立非空列的动态列表。

您可以在SSMS中运行它:

-- Create a mock-up data table.
DECLARE @Data TABLE ( column_1 VARCHAR(10), column_2 VARCHAR(10), column_3 VARCHAR(10), column_4 VARCHAR(10), column_5 VARCHAR(10), pk INT IDENTITY(1,1) );

-- Insert values into every column except for column_4.
INSERT INTO @Data ( column_1, column_2, column_3, column_5 )
    VALUES ( 'Value 1', 'Value 2', 'Value 3', 'Value 5' );

-- View @Data contents.
SELECT * FROM @Data ORDER BY pk;

-- Declare a variable to hold our non-null column list.
DECLARE @columns AS VARCHAR(MAX);

-- SQL/XML Hack: Build the non-null column list with XML's excluding of NULL values.
SELECT
    @columns = STRING_AGG ( cols.column_name, ',' )
FROM (
    SELECT CAST ( ( SELECT * FROM @Data FOR XML PATH ( '' ) ) AS XML ) AS non_null_columns
) AS x
CROSS APPLY (

    SELECT
        x.f.value('fn:local-name(.)','VARCHAR(255)') AS column_name
    FROM non_null_columns.nodes('/*') x(f)

) AS cols;

-- View the column list.
SELECT @columns AS non_null_column_list;

-- Create an executable query with the updated column list.
DECLARE @sql VARCHAR(MAX) = FORMATMESSAGE ( 'SELECT %s FROM %s;', @columns, 'dbo.TableName' );
SELECT @sql AS MyNewSelect;

此区块:

-- View @Data contents.
SELECT * FROM @Data ORDER BY pk;

返回@Data的内容:

+----------+----------+----------+----------+----------+----+
| column_1 | column_2 | column_3 | column_4 | column_5 | pk |
+----------+----------+----------+----------+----------+----+
| Value 1  | Value 2  | Value 3  | NULL     | Value 5  |  1 |
+----------+----------+----------+----------+----------+----+

此区块:

-- View the column list.
SELECT @columns AS non_null_column_list;

向我们显示变量 @columns 的内容

+----------------------------------------+
|          non_null_column_list          |
+----------------------------------------+
| column_1,column_2,column_3,column_5,pk |
+----------------------------------------+

最后,这个块:

-- Create an executable query with the updated column list.
DECLARE @sql VARCHAR(MAX) = FORMATMESSAGE ( 'SELECT %s FROM %s;', @columns, 'dbo.TableName' );
SELECT @sql AS MyNewSelect;

显示了如何完成可以用EXEC调用的动态sql语句:

+-------------------------------------------------------------------+
|                            MyNewSelect                            |
+-------------------------------------------------------------------+
| SELECT column_1,column_2,column_3,column_5,pk FROM dbo.TableName; |
+-------------------------------------------------------------------+

这绝对是 hack ,但是它将把动态SQL中的列限制为包含值的列。您确实应该考虑标准化数据以提高效率。

注意:您将需要一种方法来将派生表的XML(在我的示例中为别名“ x”)限制为特定的行。