C# 将多个SQL行合并为一个

C# 将多个SQL行合并为一个,c#,sql,sql-server,excel,sql-server-2012,C#,Sql,Sql Server,Excel,Sql Server 2012,我有一个存储过程,它连接许多表以生成一个大的结果集,然后返回到我的应用程序。应用程序依次循环遍历结果并合并特定ID上的行,并选择每行数据以包含在新对象中。这也许是用一个例子最容易解释的: Inspection, Desc, Value 1, Description1, 3 1, Description2, 2 1, Description3, 5 这是在代码中转换成的 Inspection, Descripti

我有一个存储过程,它连接许多表以生成一个大的结果集,然后返回到我的应用程序。应用程序依次循环遍历结果并合并特定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以返回更少但“更宽”的行和更多的列一样

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


另外,这是在使用Sql Server 2012。

您应该使用Sql Server
Pivot
。它将行转换为列。如果您使用的是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
编辑

正如朱哈尔在评论中所说:

生成的列名(表中的值)是在生成查询时生成的。这可能需要另一个初始查询才能获取

编辑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

这不需要枢轴,可以在大多数RDM上使用

如果您想动态地执行此操作,而不必知道所有的
Desc
值是什么,您可以构建枢轴查询并使用
Exec()
执行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的
选择部分的转换脚本

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)

使用
pivot
,它将完成尽可能草率的工作。你应该提供一个完整的答案,而不仅仅是“删除”一个功能/关键字/机制并完成它。@Amit如果有任何代码或我可以解释的东西,我一定会这样做。这是我能回答的最好的“得到建议”类型的问题。我想你可以提供一个最小的例子来说明如果问题中有样本数据,这将如何工作,或者我会对问题本身进行评论,解释为什么这样的问题不适合这样做(因为它们会导致像你这样的答案),甚至可能投票给close。但这只是我的意见…:-)(另请看@Arion的答案)对我来说没关系,我很快会尝试一下,如果你的回答能解决我试图问的问题,我会接受你的回答:)如果不能,我就必须重新措辞这个问题。同意这个样本数据。将在将来完成:)应该注意,这要求OP在构建查询时知道结果列名(表中的值)是什么。这可能需要另一个初始查询才能获取。@juharr:更新了答案谢谢。这一条提供了解决我的问题的最多提示,将其标记为公认的答案。