许多SQL行合而为一

时间:2015-11-18 13:41:24

标签: c# sql sql-server excel sql-server-2012

我有一个存储过程,它连接了许多表以生成一个大的结果集,然后返回给我的应用程序。应用程序依次遍历结果并组合特定ID上的行,并选择每行数据以包含在新对象中。使用示例解释这可能是最容易解释的:

Inspection, Desc,         Value
1,          Description1, 3       
1,          Description2, 2
1,          Description3, 5

这是代码转为

Inspection, Description1, Description2, Description3
1,          3,            2,            5

这一点是每个检验项目有一行,项目描述为标题,值为检验行和标题的单元格值。然后将其导出到Excel。

问题是:我如何在SQL Server中执行此操作,如在扩展我的SP以返回更少但是更宽的"有更多列的行?

另一个复杂因素是,一个检查可能有另一个缺少的行,在这种情况下,解决方案是添加空值或“'”。

P.S。这是使用Sql Server 2012。

3 个答案:

答案 0 :(得分:2)

如果您使用的是mssql 2005+。您可以使用这样的支点:

测试数据

DECLARE @tbl TABLE(Inspection INT, [Desc] VARCHAR(100),Value INT)
INSERT INTO @tbl
VALUES
(1,'Description1', 3),     
(1,'Description2', 2),
(1,'Description3', 5)

<强>查询

SELECT
    *
FROM
(
SELECT
    tbl.Inspection,
    tbl.[Desc],
    tbl.Value
FROM
    @tbl AS tbl
) AS tbl
PIVOT
(
    SUM(Value)
    FOR [Desc] IN ([Description1],[Description2],[Description3])
)AS pvt

<强>结果:

Inspection, Description1, Description2, Description3
1           3             2             5

修改

正如juharr在评论中所说:

生成的列名称(表中的值)是构建查询时的结果。这可能需要另一个初始查询来获取

修改2

如果您不使用mssql 2005+。或者想要和交替解释。请参阅以下查询:

SELECT
    tbl.Inspection,
    SUM(CASE WHEN [Desc]='Description1' THEN tbl.Value ELSE 0 END) AS Description1,
    SUM(CASE WHEN [Desc]='Description2' THEN tbl.Value ELSE 0 END) AS Description2,
    SUM(CASE WHEN [Desc]='Description3' THEN tbl.Value ELSE 0 END) AS Description3
FROM
    @tbl AS tbl
GROUP BY
    tbl.Inspection

这不需要一个支点,可以在大多数RDMS上使用

答案 1 :(得分:1)

您应该使用Sql Server Pivot。它将行转换为列。您可以通过this example轻松开始。

答案 2 :(得分:0)

如果您想动态执行此操作,而无需知道所有Desc值是什么,则可以构建您的数据透视查询并使用Exec()Execute sp_executesql

DECLARE @Columns NVARCHAR(MAX),
        @Sql NVARCHAR(MAX)

--Build your column headers based on Distinct Desc values
SELECT  @Columns = COALESCE(@Columns + ',', '') + QUOTENAME([Desc])
FROM    (SELECT DISTINCT [Desc] FROM tbl) t
ORDER BY [Desc]

--Build your pivot query
SET @Sql = '
    SELECT 
        *
    FROM
        tbl
    PIVOT
    (
        MAX([Value])
        FOR [Desc] IN (' + @Columns + ')
    ) p
'
EXEC(@Sql)

如果您希望-为空值,则需要创建另一个变量来保存sql的Select部分的转换脚本。

DECLARE @Columns NVARCHAR(MAX),
        @Sql NVARCHAR(MAX),
        @ColumnAliases NVARCHAR(MAX)

--Build your pivot columns based on Distinct Desc values
SELECT  @Columns = COALESCE(@Columns + ',', '') + QUOTENAME([Desc])
FROM    (SELECT DISTINCT [Desc] FROM tbl) t
ORDER BY [Desc]

--Build your column headers, replacing NULL with -
SELECT  @ColumnAliases = COALESCE(@ColumnAliases + ',', '') 
            + 'COALESCE(CONVERT(VARCHAR,' + QUOTENAME([Desc]) + '),''-'') AS ' + QUOTENAME([Desc])
FROM    (SELECT DISTINCT [Desc] FROM tbl) t
ORDER BY [Desc]


--Build your pivot query
SET @Sql = '
    SELECT 
        Inspection,'
        + @ColumnAliases + '
    FROM
        tbl
    PIVOT
    (
        MAX([Value])
        FOR [Desc] IN (' + @Columns + ')
    ) p
'
EXEC(@Sql)